xlwings-utils 25.0.4__py3-none-any.whl → 25.0.5.post0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xlwings-utils might be problematic. Click here for more details.
- xlwings_utils/xlwings_utils.py +73 -1
- {xlwings_utils-25.0.4.dist-info → xlwings_utils-25.0.5.post0.dist-info}/METADATA +94 -11
- xlwings_utils-25.0.5.post0.dist-info/RECORD +6 -0
- xlwings_utils-25.0.4.dist-info/RECORD +0 -6
- {xlwings_utils-25.0.4.dist-info → xlwings_utils-25.0.5.post0.dist-info}/WHEEL +0 -0
- {xlwings_utils-25.0.4.dist-info → xlwings_utils-25.0.5.post0.dist-info}/top_level.txt +0 -0
xlwings_utils/xlwings_utils.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
|
|
6
6
|
# |___/ |_____|
|
|
7
7
|
|
|
8
|
-
__version__ = "25.0.
|
|
8
|
+
__version__ = "25.0.5"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import dropbox
|
|
@@ -13,6 +13,7 @@ from pathlib import Path
|
|
|
13
13
|
import os
|
|
14
14
|
import sys
|
|
15
15
|
import math
|
|
16
|
+
import base64
|
|
16
17
|
|
|
17
18
|
dbx = None
|
|
18
19
|
Pythonista = sys.platform == "ios"
|
|
@@ -678,7 +679,64 @@ class block:
|
|
|
678
679
|
"""
|
|
679
680
|
return self.vlookup(s, row_from=row_from, row_to=row_to, column1=column1, column2=column2, default=default)
|
|
680
681
|
|
|
682
|
+
def decode_to_files(self):
|
|
683
|
+
"""
|
|
684
|
+
decode the block with encoded file(s) to individual local files
|
|
685
|
+
"""
|
|
686
|
+
|
|
687
|
+
row=1
|
|
688
|
+
while row<=self.number_of_rows:
|
|
689
|
+
if self[row,1] and self[row,1].startswith('<file=') and self[row,1].endswith('>'):
|
|
690
|
+
filename=self[row,1][6:-1]
|
|
691
|
+
collect=[]
|
|
692
|
+
row+=1
|
|
693
|
+
print(f"{filename=}")
|
|
694
|
+
|
|
695
|
+
while self[row,1]!='</file>':
|
|
696
|
+
print(f"{self[row,1]=}")
|
|
697
|
+
|
|
698
|
+
if self[row,1]:
|
|
699
|
+
collect.append(self[row,1])
|
|
700
|
+
row+=1
|
|
701
|
+
print(f"{collect=}")
|
|
702
|
+
decoded=base64.b64decode(''.join(collect))
|
|
703
|
+
open(filename,'wb').write(decoded)
|
|
704
|
+
row+=1
|
|
705
|
+
|
|
706
|
+
@classmethod
|
|
707
|
+
def encode_files(cls, *files):
|
|
708
|
+
"""
|
|
709
|
+
make a block with the given files encoded
|
|
710
|
+
|
|
711
|
+
Parameters
|
|
712
|
+
----------
|
|
713
|
+
files : file names (str)
|
|
714
|
+
files to be encoded
|
|
715
|
+
|
|
716
|
+
Returns
|
|
717
|
+
-------
|
|
718
|
+
block with encoded files : block
|
|
719
|
+
not minimized!
|
|
720
|
+
"""
|
|
681
721
|
|
|
722
|
+
bl =cls(number_of_rows=50000, number_of_columns=1)
|
|
723
|
+
|
|
724
|
+
n = 5000 # block size
|
|
725
|
+
row = 1
|
|
726
|
+
for file in files:
|
|
727
|
+
bl[row, 1] = f"<file={file}>"
|
|
728
|
+
row += 1
|
|
729
|
+
b64 = base64.b64encode(open(file, "rb").read()).decode("utf-8")
|
|
730
|
+
while b64:
|
|
731
|
+
b64_n = b64[:n]
|
|
732
|
+
bl[row, 1] = b64_n
|
|
733
|
+
row += 1
|
|
734
|
+
b64 = b64[n:]
|
|
735
|
+
bl[row, 1] = f"</file>"
|
|
736
|
+
row+=1
|
|
737
|
+
return bl
|
|
738
|
+
|
|
739
|
+
|
|
682
740
|
class Capture:
|
|
683
741
|
"""
|
|
684
742
|
specifies how to capture stdout
|
|
@@ -784,7 +842,21 @@ class Capture:
|
|
|
784
842
|
@include_print.setter
|
|
785
843
|
def include_print(self, value):
|
|
786
844
|
self._include_print = value
|
|
845
|
+
|
|
787
846
|
|
|
847
|
+
def trigger(sheet):
|
|
848
|
+
"""
|
|
849
|
+
triggers the macro on sheet
|
|
788
850
|
|
|
851
|
+
Parameters
|
|
852
|
+
----------
|
|
853
|
+
sheet : sheet
|
|
854
|
+
sheet to use
|
|
855
|
+
|
|
856
|
+
"""
|
|
857
|
+
|
|
858
|
+
sheet["A1"].value = "=NOW()"
|
|
859
|
+
|
|
860
|
+
|
|
789
861
|
if __name__ == "__main__":
|
|
790
862
|
...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xlwings_utils
|
|
3
|
-
Version: 25.0.
|
|
3
|
+
Version: 25.0.5.post0
|
|
4
4
|
Summary: xlwings_utils
|
|
5
5
|
Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/salabim/xlwings_utils
|
|
@@ -19,7 +19,7 @@ This module provides some useful functions to be used in xlwings (lite).
|
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
22
|
-
Just add `xlwings-utils` and `ssl` to the *requirements.txt* tab.
|
|
22
|
+
Just add `xlwings-utils` and `ssl` (even if `dropbox` is not used) to the *requirements.txt* tab.
|
|
23
23
|
|
|
24
24
|
In the script, add
|
|
25
25
|
|
|
@@ -49,7 +49,7 @@ If an application runs under xlwings, `xwu.xlwings` will be True. False, if not.
|
|
|
49
49
|
|
|
50
50
|
The xlwings lite system does not provide access to the local file system. With this module, files can be copied between Dropbox and the local pyodide file system, making it possible to indirectly use the local file system.
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Currently, it is only possible to use full-access Dropbox apps.
|
|
53
53
|
|
|
54
54
|
The easiest way to use the Dropbox functionality is to add the credentials to the environment variables. Add REFRESH_TOKEN, APP_KEY and APP_SECRET with their corresponding values to the environment variables. Instructions on how to get these variables can be found here.
|
|
55
55
|
|
|
@@ -86,7 +86,7 @@ xwu.write_dropbox('/downloads/file1.gif')
|
|
|
86
86
|
## Block support
|
|
87
87
|
|
|
88
88
|
The module contains a useful 2-dimensional data structure: *block*.
|
|
89
|
-
This can be useful
|
|
89
|
+
This can be useful for manipulating a range without accessing it directly, which is expensive in terms of memory and execution time.
|
|
90
90
|
The advantage over an ordinary list of lists is that a block is index one-based, in line with range and addressing is done with a row, column tuple.
|
|
91
91
|
So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
|
|
92
92
|
|
|
@@ -136,7 +136,7 @@ for row in range(1, 10001):
|
|
|
136
136
|
this_block[row,2]= ...
|
|
137
137
|
if ...: # end condition
|
|
138
138
|
break
|
|
139
|
-
sheet.range(10,1).value = this_block.minimized().value
|
|
139
|
+
sheet.range((10,1)).value = this_block.minimized().value
|
|
140
140
|
```
|
|
141
141
|
|
|
142
142
|
In this case, only the really processed rows are copied to the sheet.
|
|
@@ -195,11 +195,11 @@ We then read the following rows (using hlookups) and access the required values.
|
|
|
195
195
|
|
|
196
196
|
### Filling a block from other sources
|
|
197
197
|
|
|
198
|
-
The advantage of using a block instead of accessing these sources is
|
|
198
|
+
The advantage of using a block instead of accessing these sources is that they are one-based, just like in Excel.
|
|
199
199
|
|
|
200
200
|
It is possible to make a block from an xlrd worksheet with `block.from_xlrd_sheet`.
|
|
201
201
|
|
|
202
|
-
It is possible to
|
|
202
|
+
It is possible to create a block from a Pandas DataFrame using `block.from_dataframe`. Ensure that, if the dataframe is created by reading from an Excel sheet, headers=None is specified, e.g., `df = pd.read_excel(filename, header=None)`.
|
|
203
203
|
|
|
204
204
|
It is possible to make a block from an openpyxl worksheet with `block.from_openpyxl_sheet`.
|
|
205
205
|
|
|
@@ -235,9 +235,9 @@ capture = xwu.Capture(include_print=True)
|
|
|
235
235
|
|
|
236
236
|
the stdout output is captured and printed.
|
|
237
237
|
|
|
238
|
-
Capturing
|
|
238
|
+
Capturing can be enabled and disabled at any time with `capture.enabled = True` and `capture.enabled = False`.
|
|
239
239
|
|
|
240
|
-
And
|
|
240
|
+
And include print, likewise, with `capture.include_print`.
|
|
241
241
|
|
|
242
242
|
Alternatively, a context manager is provided:
|
|
243
243
|
|
|
@@ -250,7 +250,7 @@ with capture:
|
|
|
250
250
|
```
|
|
251
251
|
Note that stopping the capture, leaves the captured output in place, so it can be extended later.
|
|
252
252
|
|
|
253
|
-
In either case, the captured output can be
|
|
253
|
+
In either case, the captured output can then be copied to a sheet, like
|
|
254
254
|
|
|
255
255
|
```
|
|
256
256
|
sheet.range(4,5).value = capture.value
|
|
@@ -263,10 +263,93 @@ The capture buffer can also be retrieved as a string with `capture.str` and `cap
|
|
|
263
263
|
|
|
264
264
|
Clearing the captured stdout buffer can be done at any time with `capture.clear()`.
|
|
265
265
|
|
|
266
|
+
## Functionality for accessing local files via VBA
|
|
267
|
+
|
|
268
|
+
Currently, *xlwings Lite* does not provide access to the local file system. Therefore, xlwings_utils offers some functionality to trigger a VBA script as well as functionality to encode a file in the pyodide file system to a VBA sheet and to trigger writing the encoded file(s) to the local file system.
|
|
269
|
+
|
|
270
|
+
Note that the sheet must have a worksheet named `VBA`, and the VBA code will normally reside there.
|
|
271
|
+
|
|
272
|
+
There are three Python functions defined:
|
|
273
|
+
|
|
274
|
+
* `trigger_VBA()`
|
|
275
|
+
fires a VBA script, provided a VBA function is defined on the sheet, like:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
Sub Worksheet_Calculate()
|
|
279
|
+
If Me.Range("A1").Formula = "=NOW()" Then
|
|
280
|
+
Me.Range("A1").Value = Null
|
|
281
|
+
REM Code to run
|
|
282
|
+
End If
|
|
283
|
+
End Sub
|
|
284
|
+
```
|
|
285
|
+
* `init_transfer_files()`
|
|
286
|
+
This should be called prior to any `transfer_file` call. It just removes all encoded files from the VBA sheet (if any)
|
|
287
|
+
|
|
288
|
+
* `transfer_file()`
|
|
289
|
+
Can be used to encode a file on the pyodide file system to the VBA sheet. Multiple files are allowed. The file name will be encoded on the sheet as well.
|
|
290
|
+
|
|
291
|
+
The VBA code below can be used to decode encoded file(s) and write to the local file system.
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
Sub WriteFiles()
|
|
295
|
+
|
|
296
|
+
Dim vArr() As Byte
|
|
297
|
+
Dim S As String
|
|
298
|
+
Dim Column As Integer
|
|
299
|
+
Dim Row As Integer
|
|
300
|
+
Dim ws As Worksheet
|
|
301
|
+
Dim Count As Integer
|
|
302
|
+
Dim FileNames As String
|
|
303
|
+
|
|
304
|
+
Column = 1
|
|
305
|
+
Row = 1
|
|
306
|
+
|
|
307
|
+
ThisDir = ThisWorkbook.Path
|
|
308
|
+
Set ws = Me
|
|
309
|
+
Count = 0
|
|
310
|
+
While Row < 30000
|
|
311
|
+
Line = ws.Cells(Row, Column)
|
|
312
|
+
If InStr(Line, "<file=") = 1 And Right(Line, 1) = ">" Then
|
|
313
|
+
If Count <> 0 Then
|
|
314
|
+
FileNames = FileNames & ", "
|
|
315
|
+
End If
|
|
316
|
+
Count = Count + 1
|
|
317
|
+
FileNameOnly = Mid(Line, 7, Len(Line) - 7)
|
|
318
|
+
Filename = ThisDir & "/" & FileNameOnly
|
|
319
|
+
FileNames = FileNames & FileNameOnly
|
|
320
|
+
|
|
321
|
+
Row = Row + 1
|
|
322
|
+
S = ""
|
|
323
|
+
While ws.Cells(Row, Column) <> "</file>"
|
|
324
|
+
S = S & ws.Cells(Row, Column)
|
|
325
|
+
Row = Row + 1
|
|
326
|
+
Wend
|
|
327
|
+
|
|
328
|
+
vArr = Base64ToArray(S)
|
|
329
|
+
|
|
330
|
+
Open Filename For Binary Access Write As #1
|
|
331
|
+
WritePos = 1
|
|
332
|
+
Put #1, WritePos, vArr
|
|
333
|
+
Close #1
|
|
334
|
+
End If
|
|
335
|
+
|
|
336
|
+
Row = Row + 1
|
|
337
|
+
|
|
338
|
+
Wend
|
|
339
|
+
If Cells(4, 2) = "y" Then
|
|
340
|
+
ws.Range("A10:A1000000").Clear
|
|
341
|
+
End If
|
|
342
|
+
|
|
343
|
+
If Count = 0 Then
|
|
344
|
+
MsgBox "No files written"
|
|
345
|
+
Else
|
|
346
|
+
MsgBox "Successfully written " & Str(Count) & " file(s): " & FileNames
|
|
347
|
+
End If
|
|
348
|
+
```
|
|
266
349
|
|
|
267
350
|
## Contact info
|
|
268
351
|
|
|
269
|
-
You can contact Ruud van der Ham, the core developer,
|
|
352
|
+
You can contact Ruud van der Ham, the core developer, at ruud@salabim.org.
|
|
270
353
|
|
|
271
354
|
## Badges
|
|
272
355
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
+
xlwings_utils/xlwings_utils.py,sha256=KP4RPmEyajLF2pn9IS3QEQyYC_xBn1yNoWzdh3cqqSo,25238
|
|
3
|
+
xlwings_utils-25.0.5.post0.dist-info/METADATA,sha256=1amSYUkgWF76__slfIRyOpR-J-VbHjeoqmZxipWK21Q,13036
|
|
4
|
+
xlwings_utils-25.0.5.post0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
+
xlwings_utils-25.0.5.post0.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
+
xlwings_utils-25.0.5.post0.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
-
xlwings_utils/xlwings_utils.py,sha256=LF7niTS7WnNSoJunwuhF5OYP7yVsLK70Zt59lY0SbMs,23376
|
|
3
|
-
xlwings_utils-25.0.4.dist-info/METADATA,sha256=4pWOuXUtYWkBq4rEEDxIkmITWVECrMzh-PxdlpQ-SXc,10286
|
|
4
|
-
xlwings_utils-25.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
-
xlwings_utils-25.0.4.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
-
xlwings_utils-25.0.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|