xlwings-utils 25.0.6.post4__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.
- xlwings_utils/xlwings_utils.py +177 -49
- {xlwings_utils-25.0.6.post4.dist-info → xlwings_utils-25.0.7.dist-info}/METADATA +20 -12
- xlwings_utils-25.0.7.dist-info/RECORD +6 -0
- xlwings_utils-25.0.6.post4.dist-info/RECORD +0 -6
- {xlwings_utils-25.0.6.post4.dist-info → xlwings_utils-25.0.7.dist-info}/WHEEL +0 -0
- {xlwings_utils-25.0.6.post4.dist-info → xlwings_utils-25.0.7.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.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
|
|
|
@@ -276,83 +275,212 @@ class block:
|
|
|
276
275
|
Parameters
|
|
277
276
|
----------
|
|
278
277
|
number_of_rows : int
|
|
279
|
-
number of rows
|
|
278
|
+
number of rows (dedault 1)
|
|
280
279
|
|
|
281
280
|
number_of_columns : int
|
|
282
|
-
number of columns
|
|
281
|
+
number of columns (default 1)
|
|
283
282
|
|
|
284
283
|
Returns
|
|
285
284
|
-------
|
|
286
285
|
block
|
|
287
286
|
"""
|
|
288
287
|
|
|
289
|
-
def __init__(self,
|
|
288
|
+
def __init__(self, number_of_rows=1, number_of_columns=1):
|
|
290
289
|
self.dict = {}
|
|
291
|
-
self.
|
|
292
|
-
|
|
293
|
-
if number_of_rows is missing:
|
|
294
|
-
number_of_rows = 1
|
|
295
|
-
if number_of_columns is missing:
|
|
296
|
-
number_of_columns = 1
|
|
297
|
-
self.number_of_rows = number_of_rows
|
|
298
|
-
self.number_of_columns = number_of_columns
|
|
290
|
+
self.number_of_rows = number_of_rows
|
|
291
|
+
self.number_of_columns = number_of_columns
|
|
299
292
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
293
|
+
@classmethod
|
|
294
|
+
def from_value(cls, value, column_like=False):
|
|
295
|
+
"""
|
|
296
|
+
makes a block from a given value
|
|
297
|
+
|
|
298
|
+
Parameters
|
|
299
|
+
----------
|
|
300
|
+
value : scaler, list of scalars, list of lists of scalars or block
|
|
301
|
+
value to be used in block, possibly expanded to a list of lists of scalars
|
|
302
|
+
|
|
303
|
+
column_like : boolean
|
|
304
|
+
if value is a list of scalars, values is interpreted as a column if True, as a row otherwise
|
|
305
|
+
|
|
306
|
+
number_of_rows : int
|
|
307
|
+
if given, expand or shrink to the given number of rows
|
|
308
|
+
|
|
309
|
+
number_of_columns : int
|
|
310
|
+
if given, expand or shrink to the given number of columns
|
|
311
|
+
|
|
312
|
+
Returns
|
|
313
|
+
-------
|
|
314
|
+
block : block
|
|
315
|
+
"""
|
|
316
|
+
if isinstance(value, block):
|
|
317
|
+
value = value.value
|
|
318
|
+
if not isinstance(value, list):
|
|
319
|
+
value = [[value]]
|
|
320
|
+
if not isinstance(value[0], list):
|
|
321
|
+
if column_like:
|
|
322
|
+
value = [[item] for item in value]
|
|
323
|
+
else:
|
|
324
|
+
value = [value]
|
|
325
|
+
bl = cls(len(value), 1)
|
|
326
|
+
|
|
327
|
+
for row, row_contents in enumerate(value, 1):
|
|
328
|
+
for column, item in enumerate(row_contents, 1):
|
|
329
|
+
if item and not (isinstance(item, float) and math.isnan(item)):
|
|
330
|
+
bl.dict[row, column] = item
|
|
331
|
+
bl._number_of_columns = max(bl.number_of_columns, column)
|
|
332
|
+
return bl
|
|
308
333
|
|
|
309
334
|
@classmethod
|
|
310
|
-
def
|
|
335
|
+
def from_range(cls, rng):
|
|
336
|
+
"""
|
|
337
|
+
makes a block from a given range
|
|
338
|
+
|
|
339
|
+
Parameters
|
|
340
|
+
----------
|
|
341
|
+
rng : xlwings.Range
|
|
342
|
+
range to be used be used in block
|
|
343
|
+
|
|
344
|
+
number_of_rows : int
|
|
345
|
+
if given, expand or shrink to the given number of rows
|
|
346
|
+
|
|
347
|
+
number_of_columns : int
|
|
348
|
+
if given, expand or shrink to the given number of columns
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
block : block
|
|
353
|
+
"""
|
|
354
|
+
number_of_rows, number_of_columns = rng.shape
|
|
355
|
+
bl = cls.from_value(rng.value, column_like=(number_of_columns == 1))
|
|
356
|
+
return bl
|
|
357
|
+
|
|
358
|
+
@classmethod
|
|
359
|
+
def from_xlrd_sheet(cls, sheet):
|
|
360
|
+
"""
|
|
361
|
+
makes a block from a xlrd sheet
|
|
362
|
+
|
|
363
|
+
Parameters
|
|
364
|
+
----------
|
|
365
|
+
sheet : xlrd sheet
|
|
366
|
+
sheet to be used be used in block
|
|
367
|
+
|
|
368
|
+
number_of_rows : int
|
|
369
|
+
if given, expand or shrink to the given number of rows
|
|
370
|
+
|
|
371
|
+
number_of_columns : int
|
|
372
|
+
if given, expand or shrink to the given number of columns
|
|
373
|
+
|
|
374
|
+
Returns
|
|
375
|
+
-------
|
|
376
|
+
block : block
|
|
377
|
+
"""
|
|
311
378
|
v = [sheet.row_values(row_idx)[0 : sheet.ncols] for row_idx in range(0, sheet.nrows)]
|
|
312
|
-
return cls(v
|
|
379
|
+
return cls.from_value(v)
|
|
313
380
|
|
|
314
381
|
@classmethod
|
|
315
|
-
def from_openpyxl_sheet(cls, sheet
|
|
382
|
+
def from_openpyxl_sheet(cls, sheet):
|
|
316
383
|
v = [[cell.value for cell in row] for row in sheet.iter_rows()]
|
|
317
|
-
return cls(v
|
|
384
|
+
return cls.from_value(v)
|
|
318
385
|
|
|
319
386
|
@classmethod
|
|
320
|
-
def from_file(cls, filename
|
|
387
|
+
def from_file(cls, filename):
|
|
388
|
+
"""
|
|
389
|
+
makes a block from a file
|
|
390
|
+
|
|
391
|
+
Parameters
|
|
392
|
+
----------
|
|
393
|
+
filename : str
|
|
394
|
+
file to be used be used in block
|
|
395
|
+
|
|
396
|
+
number_of_rows : int
|
|
397
|
+
if given, expand or shrink to the given number of rows
|
|
398
|
+
|
|
399
|
+
number_of_columns : int
|
|
400
|
+
if given, expand or shrink to the given number of columns
|
|
401
|
+
|
|
402
|
+
Returns
|
|
403
|
+
-------
|
|
404
|
+
block : block
|
|
405
|
+
"""
|
|
321
406
|
with open(filename, "r") as f:
|
|
322
407
|
v = [[line if line else missing] for line in f.read().splitlines()]
|
|
323
|
-
return cls(v
|
|
408
|
+
return cls.from_value(v)
|
|
324
409
|
|
|
325
410
|
@classmethod
|
|
326
|
-
def from_dataframe(cls, df
|
|
411
|
+
def from_dataframe(cls, df):
|
|
412
|
+
"""
|
|
413
|
+
makes a block from a given dataframe
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
df : pandas dataframe
|
|
418
|
+
dataframe to be used be used in block
|
|
419
|
+
|
|
420
|
+
number_of_rows : int
|
|
421
|
+
if given, expand or shrink to the given number of rows
|
|
422
|
+
|
|
423
|
+
number_of_columns : int
|
|
424
|
+
if given, expand or shrink to the given number of columns
|
|
425
|
+
|
|
426
|
+
Returns
|
|
427
|
+
-------
|
|
428
|
+
block : block
|
|
429
|
+
"""
|
|
327
430
|
v = df.values.tolist()
|
|
328
|
-
return cls(v
|
|
431
|
+
return cls.from_value(v)
|
|
329
432
|
|
|
330
433
|
def to_openpyxl_sheet(self, sheet):
|
|
434
|
+
"""
|
|
435
|
+
makes a block from a given openpyxl sheet
|
|
436
|
+
|
|
437
|
+
Parameters
|
|
438
|
+
----------
|
|
439
|
+
sheet: openpyxl sheet
|
|
440
|
+
sheet to be used be used in block
|
|
441
|
+
|
|
442
|
+
number_of_rows : int
|
|
443
|
+
if given, expand or shrink to the given number of rows
|
|
444
|
+
|
|
445
|
+
number_of_columns : int
|
|
446
|
+
if given, expand or shrink to the given number of columns
|
|
447
|
+
|
|
448
|
+
Returns
|
|
449
|
+
-------
|
|
450
|
+
block : block
|
|
451
|
+
"""
|
|
331
452
|
for row in self.value:
|
|
332
453
|
sheet.append(row)
|
|
333
454
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
455
|
+
def reshape(self, number_of_rows=missing, number_of_columns=missing):
|
|
456
|
+
"""
|
|
457
|
+
makes a new block with given dimensions
|
|
337
458
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if not isinstance(value[0], list):
|
|
343
|
-
if self.column_like:
|
|
344
|
-
value = [[item] for item in value]
|
|
345
|
-
else:
|
|
346
|
-
value = [value]
|
|
459
|
+
Parameters
|
|
460
|
+
----------
|
|
461
|
+
number_of_rows : int
|
|
462
|
+
if given, expand or shrink to the given number of rows
|
|
347
463
|
|
|
348
|
-
|
|
349
|
-
|
|
464
|
+
number_of_columns : int
|
|
465
|
+
if given, expand or shrink to the given number of columns
|
|
350
466
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
+
|
|
481
|
+
@property
|
|
482
|
+
def value(self):
|
|
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)]
|
|
356
484
|
|
|
357
485
|
def __setitem__(self, row_column, value):
|
|
358
486
|
row, column = row_column
|
|
@@ -377,7 +505,7 @@ class block:
|
|
|
377
505
|
minimized block : block
|
|
378
506
|
uses highest_used_row_number and highest_used_column_number to minimize the block
|
|
379
507
|
"""
|
|
380
|
-
return
|
|
508
|
+
return self.reshape(number_of_rows=self.highest_used_row_number, number_of_columns=self.highest_used_column_number)
|
|
381
509
|
|
|
382
510
|
@property
|
|
383
511
|
def number_of_rows(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xlwings_utils
|
|
3
|
-
Version: 25.0.
|
|
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
|
|
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
|
|
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
|
|
94
|
+
Converting of a range to a block can be done like
|
|
95
95
|
|
|
96
96
|
```
|
|
97
|
-
|
|
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
|
-
|
|
124
|
+
It is also possible to get a copy of a block with different dimensions:
|
|
125
|
+
|
|
119
126
|
```
|
|
120
|
-
|
|
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.
|
|
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
|
-
```
|
|
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
|
|
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=znZtMTebQuTZ4ZvLITbfDlZCdzba7Avlz9RCLXq5LYk,25788
|
|
3
|
-
xlwings_utils-25.0.6.post4.dist-info/METADATA,sha256=O8dVqUWel4m__6PgnkWLR_08whGUUJGRuuy77FxfxRM,12255
|
|
4
|
-
xlwings_utils-25.0.6.post4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
-
xlwings_utils-25.0.6.post4.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
-
xlwings_utils-25.0.6.post4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|