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.

@@ -5,7 +5,7 @@
5
5
  # /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
6
6
  # |___/ |_____|
7
7
 
8
- __version__ = "25.0.5"
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
- If the file size does not match the metadata, as sometimes happens on pyodide, an OSError exception will be raised.
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
- metadata, response = dbx.files_download(dropbox_path)
183
- file_content = response.content
184
- if len(file_content) != metadata.size:
185
- raise OSError(f"file size ({len(file_content)}) does not match metadata ({metadata.size})")
186
- return file_content
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 VBA in book
849
+ triggers the macro on sheet
793
850
 
794
851
  Parameters
795
852
  ----------
796
- book : xw.Book
797
- book to use
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
- init_transfer_files should be called prior to any transfer_file()
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.5
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. If the file is not read correctly, which seems
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, via ruud@salabim.org .
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,,