xlwings-utils 25.0.5__py3-none-any.whl → 25.0.6__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 -65
- {xlwings_utils-25.0.5.dist-info → xlwings_utils-25.0.6.dist-info}/METADATA +86 -4
- xlwings_utils-25.0.6.dist-info/RECORD +6 -0
- xlwings_utils-25.0.5.dist-info/RECORD +0 -6
- {xlwings_utils-25.0.5.dist-info → xlwings_utils-25.0.6.dist-info}/WHEEL +0 -0
- {xlwings_utils-25.0.5.dist-info → xlwings_utils-25.0.6.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.6"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import dropbox
|
|
@@ -155,7 +155,7 @@ def list_dropbox(path="", recursive=False, show_files=True, show_folders=False):
|
|
|
155
155
|
return out
|
|
156
156
|
|
|
157
157
|
|
|
158
|
-
def read_dropbox(dropbox_path):
|
|
158
|
+
def read_dropbox(dropbox_path, max_retries=100):
|
|
159
159
|
"""
|
|
160
160
|
read_dropbox
|
|
161
161
|
|
|
@@ -166,6 +166,9 @@ def read_dropbox(dropbox_path):
|
|
|
166
166
|
dropbox_path : str or Pathlib.Path
|
|
167
167
|
path to read from
|
|
168
168
|
|
|
169
|
+
max_retries : int
|
|
170
|
+
number of retries (default: 100)
|
|
171
|
+
|
|
169
172
|
Returns
|
|
170
173
|
-------
|
|
171
174
|
contents of the dropbox file : bytes
|
|
@@ -175,16 +178,17 @@ def read_dropbox(dropbox_path):
|
|
|
175
178
|
If REFRESH_TOKEN, APP_KEY and APP_SECRET environment variables are specified,
|
|
176
179
|
it is not necessary to call dropbox_init() prior to any dropbox function.
|
|
177
180
|
|
|
178
|
-
|
|
181
|
+
As reading from dropbox is very unreliable under pyodide, reading will have to be retried (by default maximum 100 times).
|
|
182
|
+
The number of retries can be found with read_dropbox.retries
|
|
179
183
|
"""
|
|
180
184
|
|
|
181
185
|
_login_dbx()
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
for read_dropbox.retries in range(max_retries+1):
|
|
187
|
+
metadata, response = dbx.files_download(dropbox_path)
|
|
188
|
+
file_content = response.content
|
|
189
|
+
if len(file_content) == metadata.size:
|
|
190
|
+
return file_content
|
|
191
|
+
raise OSError(f"after {max_retries} still no valid response")
|
|
188
192
|
|
|
189
193
|
def write_dropbox(dropbox_path, contents):
|
|
190
194
|
_login_dbx()
|
|
@@ -679,6 +683,60 @@ class block:
|
|
|
679
683
|
"""
|
|
680
684
|
return self.vlookup(s, row_from=row_from, row_to=row_to, column1=column1, column2=column2, default=default)
|
|
681
685
|
|
|
686
|
+
def decode_to_files(self):
|
|
687
|
+
"""
|
|
688
|
+
decode the block with encoded file(s) to individual local files
|
|
689
|
+
"""
|
|
690
|
+
for column in self.number_of_columns:
|
|
691
|
+
row = 1
|
|
692
|
+
while row <= self.number_of_rows:
|
|
693
|
+
if self[row, column] and self[row, column].startswith("<file=") and self[row, column].endswith(">"):
|
|
694
|
+
filename = self[row, column][6:-1]
|
|
695
|
+
collect = []
|
|
696
|
+
row += 1
|
|
697
|
+
while self[row, column] != "</file>":
|
|
698
|
+
print(f"{self[row,column]=}")
|
|
699
|
+
|
|
700
|
+
if self[row, column]:
|
|
701
|
+
collect.append(self[row, column])
|
|
702
|
+
row += 1
|
|
703
|
+
decoded = base64.b64decode("".join(collect))
|
|
704
|
+
open(filename, "wb").write(decoded)
|
|
705
|
+
row += 1
|
|
706
|
+
|
|
707
|
+
@classmethod
|
|
708
|
+
def encode_files(cls, *files):
|
|
709
|
+
"""
|
|
710
|
+
make a block with the given files encoded
|
|
711
|
+
|
|
712
|
+
Parameters
|
|
713
|
+
----------
|
|
714
|
+
files : file names (str)
|
|
715
|
+
files to be encoded
|
|
716
|
+
|
|
717
|
+
Returns
|
|
718
|
+
-------
|
|
719
|
+
block with encoded files : block
|
|
720
|
+
not minimized!
|
|
721
|
+
"""
|
|
722
|
+
|
|
723
|
+
bl = cls(number_of_rows=50000, number_of_columns=1)
|
|
724
|
+
|
|
725
|
+
n = 5000 # block size
|
|
726
|
+
row = 1
|
|
727
|
+
for file in files:
|
|
728
|
+
bl[row, 1] = f"<file={file}>"
|
|
729
|
+
row += 1
|
|
730
|
+
b64 = base64.b64encode(open(file, "rb").read()).decode("utf-8")
|
|
731
|
+
while b64:
|
|
732
|
+
b64_n = b64[:n]
|
|
733
|
+
bl[row, 1] = b64_n
|
|
734
|
+
row += 1
|
|
735
|
+
b64 = b64[n:]
|
|
736
|
+
bl[row, 1] = f"</file>"
|
|
737
|
+
row += 1
|
|
738
|
+
return bl
|
|
739
|
+
|
|
682
740
|
|
|
683
741
|
class Capture:
|
|
684
742
|
"""
|
|
@@ -786,70 +844,20 @@ class Capture:
|
|
|
786
844
|
def include_print(self, value):
|
|
787
845
|
self._include_print = value
|
|
788
846
|
|
|
789
|
-
|
|
790
|
-
def trigger_VBA(book):
|
|
847
|
+
def trigger_macro(sheet):
|
|
791
848
|
"""
|
|
792
|
-
triggers the macro on sheet
|
|
849
|
+
triggers the macro on sheet
|
|
793
850
|
|
|
794
851
|
Parameters
|
|
795
852
|
----------
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
"""
|
|
853
|
+
sheet : sheet
|
|
854
|
+
sheet to use
|
|
799
855
|
|
|
800
|
-
book.sheets["VBA"]["A1"].value = "=NOW()"
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
def init_transfer_files(book):
|
|
804
|
-
"""
|
|
805
|
-
initializes the file info on sheet VBA in book
|
|
806
|
-
|
|
807
|
-
should be called prior to calling any transfer_file()
|
|
808
|
-
|
|
809
|
-
Parameters
|
|
810
|
-
----------
|
|
811
|
-
book : xw.Book
|
|
812
|
-
book to use
|
|
813
|
-
"""
|
|
814
|
-
|
|
815
|
-
global row1
|
|
816
|
-
book.sheets["VBA"].range((10, 1), (1000000, 1)).clear()
|
|
817
|
-
row1 = 10
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
def transfer_file(book, file):
|
|
821
856
|
"""
|
|
822
|
-
makes the local file to be encoded on sheet VBA in book
|
|
823
|
-
to be triggered later
|
|
824
857
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
Parameters
|
|
828
|
-
----------
|
|
829
|
-
book : xw.Book
|
|
830
|
-
book to use
|
|
831
|
-
|
|
832
|
-
file : string
|
|
833
|
-
name of file to be encoded
|
|
834
|
-
"""
|
|
835
|
-
|
|
836
|
-
global row1
|
|
837
|
-
ws = book.sheets("VBA")
|
|
838
|
-
ws_block = block(number_of_rows=50000, number_of_columns=1)
|
|
839
|
-
n = 5000 # block size
|
|
840
|
-
row = 1
|
|
841
|
-
ws_block[row, 1] = f"<file={file}>"
|
|
842
|
-
row += 1
|
|
843
|
-
b64 = base64.b64encode(open(file, "rb").read()).decode("utf-8")
|
|
844
|
-
while b64:
|
|
845
|
-
b64_n = b64[:n]
|
|
846
|
-
ws_block[row, 1] = b64_n
|
|
847
|
-
row += 1
|
|
848
|
-
b64 = b64[n:]
|
|
849
|
-
ws_block[row, 1] = f"</file>"
|
|
850
|
-
ws.range((row1, 1)).value = ws_block.minimized().value
|
|
851
|
-
row1 += ws_block.highest_used_row_number
|
|
858
|
+
sheet["A1"].value = "=NOW()"
|
|
852
859
|
|
|
853
860
|
|
|
854
861
|
if __name__ == "__main__":
|
|
855
862
|
...
|
|
863
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xlwings_utils
|
|
3
|
-
Version: 25.0.
|
|
3
|
+
Version: 25.0.6
|
|
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
|
|
@@ -62,8 +62,7 @@ python -c "exec(__import__('requests').get('https://salabim.org/dropbox setup.py
|
|
|
62
62
|
Then, it is possible to list all files in a specified folder using the list_dropbox function.
|
|
63
63
|
It is also possible to get the folders and to access all underlying folders.
|
|
64
64
|
|
|
65
|
-
The `read_dropbox` function can be used to read the contents (bytes) of a Dropbox file.
|
|
66
|
-
to happen rather frequently, an OSError exception is raised.
|
|
65
|
+
The `read_dropbox` function can be used to read the contents (bytes) of a Dropbox file. As reading from Dropbox under pyodide is very unreliable, xlwings_utils automatically retries several times (by default 100 times). The actual number of retries can be found with `read_dropbox.retries`.
|
|
67
66
|
|
|
68
67
|
The function `write_dropbox` can be used to write contents (bytes) to a Dropbox file.
|
|
69
68
|
|
|
@@ -263,10 +262,93 @@ The capture buffer can also be retrieved as a string with `capture.str` and `cap
|
|
|
263
262
|
|
|
264
263
|
Clearing the captured stdout buffer can be done at any time with `capture.clear()`.
|
|
265
264
|
|
|
265
|
+
## Functionality for accessing local files via VBA
|
|
266
|
+
|
|
267
|
+
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.
|
|
268
|
+
|
|
269
|
+
Files can be encoded into a block, like:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
bl = xwu.block.encode_files("film1.mp4", "settings.txt")
|
|
273
|
+
book.sheets["VBA"].range((10,2)).value=bl.value
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
With this code, column B will be filled with encoded copies of the files *film1.mp4* and *settings.txt* . This can then be used with a suitable VBA macro to decode to the real file system. A VBA macro can be triggered with `xwu.trigger_macro()`. This requires an Excel worksheet where cell A1 is reserved for communication with xlwings lite. This worksheet needs to contain a macro, like
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
Private Sub Worksheet_Calculate()
|
|
280
|
+
If Me.Range("A1").Formula = "=NOW()" Then
|
|
281
|
+
Me.Range("A1").Value = Null
|
|
282
|
+
Call MacroToExecute
|
|
283
|
+
End If
|
|
284
|
+
End Sub
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
, where `MacroToExecute` should contain the user code, most likely code to decode files encoded with something like
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
bl.decode_to_files()
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The VBA code below can be used to decode encoded file(s ) on a worksheet.
|
|
294
|
+
|
|
295
|
+
```
|
|
296
|
+
Sub DecodeFiles()
|
|
297
|
+
|
|
298
|
+
Dim vArr() As Byte
|
|
299
|
+
Dim S As String
|
|
300
|
+
Dim Column As Integer
|
|
301
|
+
Dim Row As Integer
|
|
302
|
+
Dim ws As Worksheet
|
|
303
|
+
Dim Count As Integer
|
|
304
|
+
Dim FileNames As String
|
|
305
|
+
|
|
306
|
+
Column = 2
|
|
307
|
+
Row = 1
|
|
308
|
+
|
|
309
|
+
ThisDir = ThisWorkbook.Path
|
|
310
|
+
Set ws = Me
|
|
311
|
+
Count = 0
|
|
312
|
+
While Row < 30000
|
|
313
|
+
Line = ws.Cells(Row, Column)
|
|
314
|
+
If InStr(Line, "<file=") = 1 And Right(Line, 1) = ">" Then
|
|
315
|
+
If Count <> 0 Then
|
|
316
|
+
FileNames = FileNames & ", "
|
|
317
|
+
End If
|
|
318
|
+
Count = Count + 1
|
|
319
|
+
FileNameOnly = Mid(Line, 7, Len(Line) - 7)
|
|
320
|
+
Filename = ThisDir & "/" & FileNameOnly
|
|
321
|
+
FileNames = FileNames & FileNameOnly
|
|
322
|
+
|
|
323
|
+
Row = Row + 1
|
|
324
|
+
S = ""
|
|
325
|
+
While ws.Cells(Row, Column) <> "</file>"
|
|
326
|
+
S = S & ws.Cells(Row, Column)
|
|
327
|
+
Row = Row + 1
|
|
328
|
+
Wend
|
|
329
|
+
|
|
330
|
+
vArr = Base64ToArray(S)
|
|
331
|
+
|
|
332
|
+
Open Filename For Binary Access Write As #1
|
|
333
|
+
WritePos = 1
|
|
334
|
+
Put #1, WritePos, vArr
|
|
335
|
+
Close #1
|
|
336
|
+
End If
|
|
337
|
+
|
|
338
|
+
Row = Row + 1
|
|
339
|
+
|
|
340
|
+
Wend
|
|
341
|
+
|
|
342
|
+
If Count = 0 Then
|
|
343
|
+
MsgBox "No files to decode"
|
|
344
|
+
Else
|
|
345
|
+
MsgBox "Successfully decoded and written " & Str(Count) & " file(s): " & FileNames
|
|
346
|
+
End If
|
|
347
|
+
```
|
|
266
348
|
|
|
267
349
|
## Contact info
|
|
268
350
|
|
|
269
|
-
You can contact Ruud van der Ham, the core developer,
|
|
351
|
+
You can contact Ruud van der Ham, the core developer, at ruud@salabim.org.
|
|
270
352
|
|
|
271
353
|
## Badges
|
|
272
354
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
+
xlwings_utils/xlwings_utils.py,sha256=5glVg37dkRfHSBT-gcSK-aKqAl-prDmRYcVh-Im0wt4,25463
|
|
3
|
+
xlwings_utils-25.0.6.dist-info/METADATA,sha256=aK8ufY5s5Wp7x1iU11g2dRNGaWRXOx67VAsM0wJJV6I,13139
|
|
4
|
+
xlwings_utils-25.0.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
+
xlwings_utils-25.0.6.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
+
xlwings_utils-25.0.6.dist-info/RECORD,,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
-
xlwings_utils/xlwings_utils.py,sha256=LT2NxlvS0T9wY4Qi9UiINpS1S1nmM2IutoBgkWk3JDo,24760
|
|
3
|
-
xlwings_utils-25.0.5.dist-info/METADATA,sha256=MBHmRPFi-ytcOioOS2oII7pWN9e6SyOXHV_M3CVSJBs,10317
|
|
4
|
-
xlwings_utils-25.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
-
xlwings_utils-25.0.5.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
-
xlwings_utils-25.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|