xlwings-utils 25.0.6.post5__py3-none-any.whl → 25.0.7__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.6"
8
+ __version__ = "25.0.7"
9
9
 
10
10
 
11
11
  import dropbox
@@ -20,7 +20,6 @@ Pythonista = sys.platform == "ios"
20
20
  try:
21
21
  import xlwings
22
22
 
23
- xlwings = True
24
23
  except ImportError:
25
24
  xlwings = False
26
25
 
@@ -268,6 +267,7 @@ def read_local(path):
268
267
  contents = f.read()
269
268
  return contents
270
269
 
270
+
271
271
  class block:
272
272
  """
273
273
  block is 2 dimensional data structure with 1 as lowest index (like xlwings range)
@@ -291,9 +291,7 @@ class block:
291
291
  self.number_of_columns = number_of_columns
292
292
 
293
293
  @classmethod
294
- def from_value(
295
- cls, value, column_like=False, number_of_rows=missing, number_of_columns=missing
296
- ):
294
+ def from_value(cls, value, column_like=False):
297
295
  """
298
296
  makes a block from a given value
299
297
 
@@ -331,14 +329,10 @@ class block:
331
329
  if item and not (isinstance(item, float) and math.isnan(item)):
332
330
  bl.dict[row, column] = item
333
331
  bl._number_of_columns = max(bl.number_of_columns, column)
334
- if number_of_rows is not missing:
335
- bl.number_of_rows = number_of_rows
336
- if number_of_columns is not missing:
337
- bl.number_of_columns = number_of_columns
338
332
  return bl
339
333
 
340
334
  @classmethod
341
- def from_range(cls, rng, number_of_rows=missing, number_of_columns=missing):
335
+ def from_range(cls, rng):
342
336
  """
343
337
  makes a block from a given range
344
338
 
@@ -358,16 +352,11 @@ class block:
358
352
  block : block
359
353
  """
360
354
  number_of_rows, number_of_columns = rng.shape
361
- bl = cls.from_value(
362
- rng.value,
363
- column_like=(number_of_columns == 1),
364
- number_of_rows=number_of_rows,
365
- number_of_columns=number_of_columns,
366
- )
355
+ bl = cls.from_value(rng.value, column_like=(number_of_columns == 1))
367
356
  return bl
368
357
 
369
358
  @classmethod
370
- def from_xlrd_sheet(cls, sheet, number_of_rows=missing, number_of_columns=missing):
359
+ def from_xlrd_sheet(cls, sheet):
371
360
  """
372
361
  makes a block from a xlrd sheet
373
362
 
@@ -386,25 +375,16 @@ class block:
386
375
  -------
387
376
  block : block
388
377
  """
389
- v = [
390
- sheet.row_values(row_idx)[0 : sheet.ncols]
391
- for row_idx in range(0, sheet.nrows)
392
- ]
393
- return cls.from_value(
394
- v, number_of_rows=number_of_rows, number_of_columns=number_of_columns
395
- )
378
+ v = [sheet.row_values(row_idx)[0 : sheet.ncols] for row_idx in range(0, sheet.nrows)]
379
+ return cls.from_value(v)
396
380
 
397
381
  @classmethod
398
- def from_openpyxl_sheet(
399
- cls, sheet, number_of_rows=missing, number_of_columns=missing
400
- ):
382
+ def from_openpyxl_sheet(cls, sheet):
401
383
  v = [[cell.value for cell in row] for row in sheet.iter_rows()]
402
- return cls.from_value(
403
- v, number_of_rows=number_of_rows, number_of_columns=number_of_columns
404
- )
384
+ return cls.from_value(v)
405
385
 
406
386
  @classmethod
407
- def from_file(cls, filename, number_of_rows=missing, number_of_columns=missing):
387
+ def from_file(cls, filename):
408
388
  """
409
389
  makes a block from a file
410
390
 
@@ -425,12 +405,10 @@ class block:
425
405
  """
426
406
  with open(filename, "r") as f:
427
407
  v = [[line if line else missing] for line in f.read().splitlines()]
428
- return cls.from_value(
429
- v, number_of_rows=number_of_rows, number_of_columns=number_of_columns
430
- )
408
+ return cls.from_value(v)
431
409
 
432
410
  @classmethod
433
- def from_dataframe(cls, df, number_of_rows=missing, number_of_columns=missing):
411
+ def from_dataframe(cls, df):
434
412
  """
435
413
  makes a block from a given dataframe
436
414
 
@@ -450,9 +428,7 @@ class block:
450
428
  block : block
451
429
  """
452
430
  v = df.values.tolist()
453
- return cls.from_value(
454
- v, number_of_rows=number_of_rows, number_of_columns=number_of_columns
455
- )
431
+ return cls.from_value(v)
456
432
 
457
433
  def to_openpyxl_sheet(self, sheet):
458
434
  """
@@ -476,38 +452,50 @@ class block:
476
452
  for row in self.value:
477
453
  sheet.append(row)
478
454
 
455
+ def reshape(self, number_of_rows=missing, number_of_columns=missing):
456
+ """
457
+ makes a new block with given dimensions
458
+
459
+ Parameters
460
+ ----------
461
+ number_of_rows : int
462
+ if given, expand or shrink to the given number of rows
463
+
464
+ number_of_columns : int
465
+ if given, expand or shrink to the given number of columns
466
+
467
+ Returns
468
+ -------
469
+ block : block
470
+ """
471
+ if number_of_rows is missing:
472
+ number_of_rows = self.number_of_rows
473
+ if number_of_columns is missing:
474
+ number_of_columns = self.number_of_columns
475
+ bl = block(number_of_rows=number_of_rows, number_of_columns=number_of_columns)
476
+ for (row, column), value in self.dict.items():
477
+ if row <= number_of_columns and column <= number_of_columns:
478
+ bl.dict[row, column] = value
479
+ return bl
480
+
479
481
  @property
480
482
  def value(self):
481
- return [
482
- [
483
- self.dict.get((row, column))
484
- for column in range(1, self.number_of_columns + 1)
485
- ]
486
- for row in range(1, self.number_of_rows + 1)
487
- ]
483
+ return [[self.dict.get((row, column)) for column in range(1, self.number_of_columns + 1)] for row in range(1, self.number_of_rows + 1)]
488
484
 
489
485
  def __setitem__(self, row_column, value):
490
486
  row, column = row_column
491
487
  if row < 1 or row > self.number_of_rows:
492
- raise IndexError(
493
- f"row must be between 1 and {self.number_of_rows} not {row}"
494
- )
488
+ raise IndexError(f"row must be between 1 and {self.number_of_rows} not {row}")
495
489
  if column < 1 or column > self.number_of_columns:
496
- raise IndexError(
497
- f"column must be between 1 and {self.number_of_columns} not {column}"
498
- )
490
+ raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
499
491
  self.dict[row, column] = value
500
492
 
501
493
  def __getitem__(self, row_column):
502
494
  row, column = row_column
503
495
  if row < 1 or row > self.number_of_rows:
504
- raise IndexError(
505
- f"row must be between 1 and {self.number_of_rows} not {row}"
506
- )
496
+ raise IndexError(f"row must be between 1 and {self.number_of_rows} not {row}")
507
497
  if column < 1 or column > self.number_of_columns:
508
- raise IndexError(
509
- f"column must be between 1 and {self.number_of_columns} not {column}"
510
- )
498
+ raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
511
499
  return self.dict.get((row, column))
512
500
 
513
501
  def minimized(self):
@@ -517,11 +505,7 @@ class block:
517
505
  minimized block : block
518
506
  uses highest_used_row_number and highest_used_column_number to minimize the block
519
507
  """
520
- return block.from_value(
521
- self,
522
- number_of_rows=self.highest_used_row_number,
523
- number_of_columns=self.highest_used_column_number,
524
- )
508
+ return self.reshape(number_of_rows=self.highest_used_row_number, number_of_columns=self.highest_used_column_number)
525
509
 
526
510
  @property
527
511
  def number_of_rows(self):
@@ -576,9 +560,7 @@ class block:
576
560
  if column < 1:
577
561
  raise ValueError(f"{name}={column} < 1")
578
562
  if column > self.number_of_columns:
579
- raise ValueError(
580
- f"{name}={column} > number_of_columns={self.number_of_columns}"
581
- )
563
+ raise ValueError(f"{name}={column} > number_of_columns={self.number_of_columns}")
582
564
 
583
565
  def transpose(self):
584
566
  """
@@ -588,23 +570,12 @@ class block:
588
570
  -------
589
571
  transposed block : block
590
572
  """
591
- bl = block(
592
- number_of_rows=self.number_of_columns, number_of_columns=self.number_of_rows
593
- )
573
+ bl = block(number_of_rows=self.number_of_columns, number_of_columns=self.number_of_rows)
594
574
  for (row, column), value in self.dict.items():
595
575
  bl[column, row] = value
596
576
  return bl
597
577
 
598
- def vlookup(
599
- self,
600
- s,
601
- *,
602
- row_from=1,
603
- row_to=missing,
604
- column1=1,
605
- column2=missing,
606
- default=missing,
607
- ):
578
+ def vlookup(self, s, *, row_from=1, row_to=missing, column1=1, column2=missing, default=missing):
608
579
  """
609
580
  searches in column1 for row between row_from and row_to for s and returns the value found at (that row, column2)
610
581
 
@@ -645,9 +616,7 @@ class block:
645
616
  if column2 is missing:
646
617
  column2 = column1 + 1
647
618
  self._check_column(column2, "column2")
648
- row = self.lookup_row(
649
- s, row_from=row_from, row_to=row_to, column1=column1, default=-1
650
- )
619
+ row = self.lookup_row(s, row_from=row_from, row_to=row_to, column1=column1, default=-1)
651
620
  if row == -1:
652
621
  if default is missing:
653
622
  raise ValueError(f"{s} not found]")
@@ -712,16 +681,7 @@ class block:
712
681
  else:
713
682
  return default
714
683
 
715
- def hlookup(
716
- self,
717
- s,
718
- *,
719
- column_from=1,
720
- column_to=missing,
721
- row1=1,
722
- row2=missing,
723
- default=missing,
724
- ):
684
+ def hlookup(self, s, *, column_from=1, column_to=missing, row1=1, row2=missing, default=missing):
725
685
  """
726
686
  searches in row1 for column between column_from and column_to for s and returns the value found at (that column, row2)
727
687
 
@@ -762,9 +722,7 @@ class block:
762
722
  if row2 is missing:
763
723
  row2 = row1 + 1
764
724
  self._check_row(row2, "row2")
765
- column = self.lookup_column(
766
- s, column_from=column_from, column_to=column_to, row1=row1, default=-1
767
- )
725
+ column = self.lookup_column(s, column_from=column_from, column_to=column_to, row1=row1, default=-1)
768
726
  if column == -1:
769
727
  if default is missing:
770
728
  raise ValueError(f"{s} not found")
@@ -773,9 +731,7 @@ class block:
773
731
  else:
774
732
  return self[row2, column]
775
733
 
776
- def lookup_column(
777
- self, s, *, column_from=1, column_to=missing, row1=1, default=missing
778
- ):
734
+ def lookup_column(self, s, *, column_from=1, column_to=missing, row1=1, default=missing):
779
735
  """
780
736
  searches in row1 for column between column_from and column_to for s and returns that column number
781
737
 
@@ -825,16 +781,7 @@ class block:
825
781
  else:
826
782
  return default
827
783
 
828
- def lookup(
829
- self,
830
- s,
831
- *,
832
- row_from=1,
833
- row_to=missing,
834
- column1=1,
835
- column2=missing,
836
- default=missing,
837
- ):
784
+ def lookup(self, s, *, row_from=1, row_to=missing, column1=1, column2=missing, default=missing):
838
785
  """
839
786
  searches in column1 for row between row_from and row_to for s and returns the value found at (that row, column2)
840
787
 
@@ -876,14 +823,7 @@ class block:
876
823
  ----
877
824
  This is exactly the same as vlookup.
878
825
  """
879
- return self.vlookup(
880
- s,
881
- row_from=row_from,
882
- row_to=row_to,
883
- column1=column1,
884
- column2=column2,
885
- default=default,
886
- )
826
+ return self.vlookup(s, row_from=row_from, row_to=row_to, column1=column1, column2=column2, default=default)
887
827
 
888
828
  def decode_to_files(self):
889
829
  """
@@ -894,11 +834,7 @@ class block:
894
834
  row = 1
895
835
  bl = self.minimized()
896
836
  while row <= self.number_of_rows:
897
- if (
898
- self[row, column]
899
- and self[row, column].startswith("<file=")
900
- and self[row, column].endswith(">")
901
- ):
837
+ if self[row, column] and self[row, column].startswith("<file=") and self[row, column].endswith(">"):
902
838
  filename = self[row, column][6:-1]
903
839
  collect = []
904
840
  row += 1
@@ -943,6 +879,7 @@ class block:
943
879
  row += 1
944
880
  return bl.minimized()
945
881
 
882
+
946
883
  class Capture:
947
884
  """
948
885
  specifies how to capture stdout
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xlwings_utils
3
- Version: 25.0.6.post5
3
+ Version: 25.0.7
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
@@ -87,14 +87,20 @@ xwu.write_dropbox('/downloads/file1.gif')
87
87
  The module contains a useful 2-dimensional data structure: *block*.
88
88
  This can be useful for manipulating a range without accessing it directly, which is expensive in terms of memory and execution time.
89
89
  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.
90
- So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
90
+ So, `my_block[row, col]` is roughly equivalent to `lol[row-1][col-1]`
91
91
 
92
- A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value` or `block.value_keep`.
92
+ A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value`.
93
93
 
94
- Converting the value of a range (usually a list of lists, but can also be a list or scalar) to a block can be done with
94
+ Converting of a range to a block can be done like
95
95
 
96
96
  ```
97
- my_block = xwu.block.from_value(range.value)
97
+ rng = book.sheets.active.range((5,7),(8,100))
98
+ my_block = xwu.block.from_range(rng
99
+ ```
100
+
101
+ A value of a range (list of lists, list of scalars or scalar can be converted to a block with
102
+ ```
103
+ my_block = xwu.block.from_value(rng.value)
98
104
  ```
99
105
  The dimensions (number of rows and number of columns) are automatically set.
100
106
 
@@ -115,9 +121,10 @@ block = xwu.block(number_of_rows, number_columns)
115
121
  The dimensions can be queried or redefined with `block.number_of_rows` and
116
122
  `block.number_of_columns`.
117
123
 
118
- To assign a block to range, use
124
+ It is also possible to get a copy of a block with different dimensions:
125
+
119
126
  ```
120
- range.value = block.value
127
+ bl = my.block.reshape(number_of_rows=2, number_of_columns=10)
121
128
  ```
122
129
 
123
130
  The property `block.highest_used_row_number` returns the row number of the highest non-None cell.
@@ -152,7 +159,7 @@ Of course, we could access the various input fields with absolute ranges, but if
152
159
  If we read the project sheet (partly) into a block, lookup methods are available to access *fields* easily and future-proof:
153
160
 
154
161
  ```
155
- bl = xwu.block.from_value(sheet.range((0,0),(100,10)).value)
162
+ bl = xwu.block.from_range(sheet.range(1,1),(100,10)))
156
163
  ```
157
164
 
158
165
  Let's see how this works with the above sheet. The corresponding block (bl) looks like
@@ -171,7 +178,8 @@ Let's see how this works with the above sheet. The corresponding block (bl) look
171
178
  9 |
172
179
  ```
173
180
  Now we can do
174
- ```project = bl.lookup("Project")
181
+ ```
182
+ project = bl.lookup("Project")
175
183
  project = bl.lookup("Project")
176
184
  start_date = bl.lookup("Start date")
177
185
  end_date = bl.lookup("End date")
@@ -194,11 +202,11 @@ We then read the following rows (using hlookups) and access the required values.
194
202
 
195
203
  ### Filling a block from other sources
196
204
 
197
- The advantage of using a block instead of accessing these sources is that they are one-based, just like in Excel.
205
+ The advantage of using a block instead of accessing these sources directly is that they are one-based, just like in Excel.
198
206
 
199
207
  It is possible to make a block from an xlrd worksheet with `block.from_xlrd_sheet`.
200
208
 
201
- 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)`.
209
+ It is possible to create a block from a panda 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)`.
202
210
 
203
211
  It is possible to make a block from an openpyxl worksheet with `block.from_openpyxl_sheet`.
204
212
 
@@ -293,7 +301,7 @@ Just add the .bas file to a worksheet and call like
293
301
  Sub MacroToExecute()
294
302
  DecodeFile(Me, 10, 1)
295
303
  ```
296
-
304
+
297
305
  In this example, the file *film1.mp4* will be downloaded into the current directory.
298
306
 
299
307
  The module xlwings_utils also contains code to encode a local file to a sheet:
@@ -0,0 +1,6 @@
1
+ xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
2
+ xlwings_utils/xlwings_utils.py,sha256=e8Lo40ceG0kSzSuytOpIT3cvJ_bhZRxLC2x69EE6k9Y,28725
3
+ xlwings_utils-25.0.7.dist-info/METADATA,sha256=NVLthhuk58Inh4nNVC9Bvue1VEUXuRUYdjJYKlhEqyA,12418
4
+ xlwings_utils-25.0.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ xlwings_utils-25.0.7.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
6
+ xlwings_utils-25.0.7.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
2
- xlwings_utils/xlwings_utils.py,sha256=2OxAeSEvIxSrj5aMMIxAsFYthYKk9yaYVvo8phtaf1c,29626
3
- xlwings_utils-25.0.6.post5.dist-info/METADATA,sha256=8Ub-c1wDWkoZcW5qXie2w2gqItVa3RMPLjpKaZN7pt8,12255
4
- xlwings_utils-25.0.6.post5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- xlwings_utils-25.0.6.post5.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
6
- xlwings_utils-25.0.6.post5.dist-info/RECORD,,