xlwings-utils 0.0.5__py3-none-any.whl → 0.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 +169 -79
- xlwings_utils-0.0.7.dist-info/METADATA +132 -0
- xlwings_utils-0.0.7.dist-info/RECORD +6 -0
- {xlwings_utils-0.0.5.dist-info → xlwings_utils-0.0.7.dist-info}/WHEEL +1 -1
- xlwings_utils-0.0.5.dist-info/METADATA +0 -43
- xlwings_utils-0.0.5.dist-info/RECORD +0 -6
- {xlwings_utils-0.0.5.dist-info → xlwings_utils-0.0.7.dist-info}/top_level.txt +0 -0
xlwings_utils/xlwings_utils.py
CHANGED
|
@@ -5,22 +5,27 @@
|
|
|
5
5
|
# /_/\_\|_| \_/\_/ |_||_| |_| \__, ||___/ _____ \__,_| \__||_||_||___/
|
|
6
6
|
# |___/ |_____|
|
|
7
7
|
|
|
8
|
-
__version__ = "0.0.
|
|
8
|
+
__version__ = "0.0.7"
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
import dropbox
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
import os
|
|
14
|
+
import sys
|
|
14
15
|
|
|
15
16
|
_captured_stdout = []
|
|
16
17
|
dbx = None
|
|
18
|
+
Pythonista = sys.platform == "ios"
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
def dropbox_init(refresh_token=None, app_key=None, app_secret=None):
|
|
20
22
|
"""
|
|
21
23
|
dropbox initialize
|
|
22
24
|
|
|
23
|
-
This function
|
|
25
|
+
This function may to be called prior to using any dropbox function
|
|
26
|
+
to specify the request token, app key and app secret.
|
|
27
|
+
If these are specified as REFRESH_TOKEN, APP_KEY and APP_SECRET
|
|
28
|
+
environment variables, it is no necessary to call dropbox_init().
|
|
24
29
|
|
|
25
30
|
Parameters
|
|
26
31
|
----------
|
|
@@ -44,54 +49,99 @@ def dropbox_init(refresh_token=None, app_key=None, app_secret=None):
|
|
|
44
49
|
-------
|
|
45
50
|
-
|
|
46
51
|
"""
|
|
52
|
+
global dbx
|
|
53
|
+
|
|
54
|
+
if Pythonista:
|
|
55
|
+
# under Pythonista, the environ is updated from the .environ.toml file, if present
|
|
56
|
+
environ_file = Path(os.environ["HOME"]) / "Documents" / ".environ.toml"
|
|
57
|
+
|
|
58
|
+
if environ_file.is_file():
|
|
59
|
+
with open(environ_file, "r") as f:
|
|
60
|
+
import toml
|
|
61
|
+
|
|
62
|
+
d = toml.load(f)
|
|
63
|
+
os.environ.update(d)
|
|
64
|
+
|
|
47
65
|
if refresh_token is None:
|
|
48
|
-
|
|
66
|
+
if "REFRESH_TOKEN" in os.environ:
|
|
67
|
+
refresh_token = os.environ["REFRESH_TOKEN"]
|
|
68
|
+
else:
|
|
69
|
+
raise ValueError("no REFRESH_TOKEN found in environment.")
|
|
49
70
|
if app_key is None:
|
|
50
|
-
|
|
71
|
+
if "APP_KEY" in os.environ:
|
|
72
|
+
app_key = os.environ["APP_KEY"]
|
|
73
|
+
else:
|
|
74
|
+
raise ValueError("no APP_KEY found in environment.")
|
|
51
75
|
if app_secret is None:
|
|
52
|
-
|
|
76
|
+
if "APP_SECRET" in os.environ:
|
|
77
|
+
app_secret = os.environ["APP_SECRET"]
|
|
78
|
+
else:
|
|
79
|
+
raise ValueError("no APP_SECRET found in environment.")
|
|
53
80
|
|
|
54
|
-
global dbx
|
|
55
81
|
dbx = dropbox.Dropbox(oauth2_refresh_token=refresh_token, app_key=app_key, app_secret=app_secret)
|
|
82
|
+
try:
|
|
83
|
+
dbx.files_list_folder(path="") # just to test proper credentials
|
|
84
|
+
except dropbox.exceptions.AuthError:
|
|
85
|
+
raise ValueError("invalid dropbox credentials")
|
|
56
86
|
|
|
57
87
|
|
|
58
|
-
def
|
|
88
|
+
def _login_dbx():
|
|
59
89
|
if dbx is None:
|
|
60
|
-
|
|
90
|
+
dropbox_init() # use environment
|
|
61
91
|
|
|
62
92
|
|
|
63
|
-
def list_dropbox(path="", recursive=False):
|
|
93
|
+
def list_dropbox(path="", recursive=False, show_files=True, show_folders=False):
|
|
64
94
|
"""
|
|
65
95
|
list_dropbox
|
|
66
96
|
|
|
67
|
-
returns all dropbox files in path
|
|
97
|
+
returns all dropbox files/folders in path
|
|
68
98
|
|
|
69
99
|
Parameters
|
|
70
100
|
----------
|
|
71
101
|
path : str or Pathlib.Path
|
|
72
102
|
path from which to list all files (default: '')
|
|
73
103
|
|
|
74
|
-
|
|
75
104
|
recursive : bool
|
|
76
105
|
if True, recursively list files. if False (default) no recursion
|
|
77
106
|
|
|
107
|
+
show_files : bool
|
|
108
|
+
if True (default), show file entries
|
|
109
|
+
if False, do not show file entries
|
|
110
|
+
|
|
111
|
+
show_folders : bool
|
|
112
|
+
if True, show folder entries
|
|
113
|
+
if False (default), do not show folder entries
|
|
114
|
+
|
|
78
115
|
Returns
|
|
79
116
|
-------
|
|
80
|
-
files
|
|
117
|
+
files : list
|
|
118
|
+
|
|
119
|
+
Note
|
|
120
|
+
----
|
|
121
|
+
Directory entries are never returned
|
|
122
|
+
|
|
123
|
+
Note
|
|
124
|
+
----
|
|
125
|
+
If REFRESH_TOKEN, APP_KEY and APP_SECRET environment variables are specified,
|
|
126
|
+
it is not necessary to call dropbox_init() prior to any dropbox function.
|
|
81
127
|
"""
|
|
82
|
-
|
|
128
|
+
_login_dbx()
|
|
83
129
|
out = []
|
|
84
130
|
result = dbx.files_list_folder(path, recursive=recursive)
|
|
85
131
|
|
|
86
132
|
for entry in result.entries:
|
|
87
|
-
if isinstance(entry, dropbox.files.FileMetadata):
|
|
133
|
+
if show_files and isinstance(entry, dropbox.files.FileMetadata):
|
|
88
134
|
out.append(entry.path_display)
|
|
135
|
+
if show_folders and isinstance(entry, dropbox.files.FolderMetadata):
|
|
136
|
+
out.append(entry.path_display + "/")
|
|
89
137
|
|
|
90
138
|
while result.has_more:
|
|
91
139
|
result = dbx.files_list_folder_continue(result.cursor)
|
|
92
140
|
for entry in result.entries:
|
|
93
|
-
if isinstance(entry, dropbox.files.FileMetadata):
|
|
141
|
+
if show_files and isinstance(entry, dropbox.files.FileMetadata):
|
|
94
142
|
out.append(entry.path_display)
|
|
143
|
+
if show_folders and isinstance(entry, dropbox.files.FolderMetadata):
|
|
144
|
+
out.append(entry.path_display + "/")
|
|
95
145
|
|
|
96
146
|
return out
|
|
97
147
|
|
|
@@ -110,16 +160,21 @@ def read_dropbox(dropbox_path):
|
|
|
110
160
|
Returns
|
|
111
161
|
-------
|
|
112
162
|
contents of the dropbox file : bytes
|
|
163
|
+
|
|
164
|
+
Note
|
|
165
|
+
----
|
|
166
|
+
If REFRESH_TOKEN, APP_KEY and APP_SECRET environment variables are specified,
|
|
167
|
+
it is not necessary to call dropbox_init() prior to any dropbox function.
|
|
113
168
|
"""
|
|
114
169
|
|
|
115
|
-
|
|
170
|
+
_login_dbx()
|
|
116
171
|
metadata, response = dbx.files_download(dropbox_path)
|
|
117
172
|
file_content = response.content
|
|
118
173
|
return file_content
|
|
119
174
|
|
|
120
175
|
|
|
121
176
|
def write_dropbox(dropbox_path, contents):
|
|
122
|
-
|
|
177
|
+
_login_dbx()
|
|
123
178
|
"""
|
|
124
179
|
write_dropbox
|
|
125
180
|
|
|
@@ -133,13 +188,53 @@ def write_dropbox(dropbox_path, contents):
|
|
|
133
188
|
contents : bytes
|
|
134
189
|
contents to be written
|
|
135
190
|
|
|
191
|
+
Note
|
|
192
|
+
----
|
|
193
|
+
If REFRESH_TOKEN, APP_KEY and APP_SECRET environment variables are specified,
|
|
194
|
+
it is not necessary to call dropbox_init() prior to any dropbox function.
|
|
136
195
|
"""
|
|
137
196
|
dbx.files_upload(contents, dropbox_path, mode=dropbox.files.WriteMode.overwrite)
|
|
138
197
|
|
|
139
198
|
|
|
140
|
-
def list_local(path):
|
|
199
|
+
def list_local(path, recursive=False, show_files=True, show_folders=False):
|
|
200
|
+
"""
|
|
201
|
+
list_local
|
|
202
|
+
|
|
203
|
+
returns all local files/folders in path
|
|
204
|
+
|
|
205
|
+
Parameters
|
|
206
|
+
----------
|
|
207
|
+
path : str or Pathlib.Path
|
|
208
|
+
path from which to list all files (default: '')
|
|
209
|
+
|
|
210
|
+
recursive : bool
|
|
211
|
+
if True, recursively list files. if False (default) no recursion
|
|
212
|
+
|
|
213
|
+
show_files : bool
|
|
214
|
+
if True (default), show file entries
|
|
215
|
+
if False, do not show file entries
|
|
216
|
+
|
|
217
|
+
show_folders : bool
|
|
218
|
+
if True, show folder entries
|
|
219
|
+
if False (default), do not show folder entries
|
|
220
|
+
|
|
221
|
+
Returns
|
|
222
|
+
-------
|
|
223
|
+
files, relative to path : list
|
|
224
|
+
"""
|
|
141
225
|
path = Path(path)
|
|
142
|
-
|
|
226
|
+
|
|
227
|
+
result = []
|
|
228
|
+
for entry in path.iterdir():
|
|
229
|
+
if entry.is_file():
|
|
230
|
+
if show_files:
|
|
231
|
+
result.append(str(entry))
|
|
232
|
+
elif entry.is_dir():
|
|
233
|
+
if show_folders:
|
|
234
|
+
result.append(str(entry) + "/")
|
|
235
|
+
if recursive:
|
|
236
|
+
result.extend(list_local(entry, recursive=recursive, show_files=show_files, show_folders=show_folders))
|
|
237
|
+
return result
|
|
143
238
|
|
|
144
239
|
|
|
145
240
|
def write_local(path, contents):
|
|
@@ -173,55 +268,51 @@ class block:
|
|
|
173
268
|
block
|
|
174
269
|
"""
|
|
175
270
|
|
|
176
|
-
def __init__(self, number_of_rows, number_of_columns):
|
|
271
|
+
def __init__(self, value=None, *, number_of_rows=None, number_of_columns=None,column_like=False):
|
|
177
272
|
self.dict = {}
|
|
178
|
-
self.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if not isinstance(list_of_lists[0], list):
|
|
209
|
-
if column_like:
|
|
210
|
-
list_of_lists = [[value] for value in list_of_lists]
|
|
273
|
+
self.column_like=column_like
|
|
274
|
+
if value is None:
|
|
275
|
+
if number_of_rows is None:
|
|
276
|
+
number_of_rows=1
|
|
277
|
+
if number_of_columns is None:
|
|
278
|
+
number_of_columns=1
|
|
279
|
+
self.number_of_rows=number_of_rows
|
|
280
|
+
self.number_of_columns=number_of_columns
|
|
281
|
+
|
|
282
|
+
else:
|
|
283
|
+
if isinstance(value,block):
|
|
284
|
+
value=value.value
|
|
285
|
+
self.value=value
|
|
286
|
+
if number_of_rows is not None:
|
|
287
|
+
self.number_of_rows=number_of_rows
|
|
288
|
+
if number_of_columns is not None:
|
|
289
|
+
self.number_of_columns=number_of_columns
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@property
|
|
293
|
+
def value(self):
|
|
294
|
+
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)]
|
|
295
|
+
|
|
296
|
+
@value.setter
|
|
297
|
+
def value(self,value):
|
|
298
|
+
if not isinstance(value, list):
|
|
299
|
+
value = [[value]]
|
|
300
|
+
if not isinstance(value[0], list):
|
|
301
|
+
if self.column_like:
|
|
302
|
+
value = [[item] for item in value]
|
|
211
303
|
else:
|
|
212
|
-
|
|
304
|
+
value = [value]
|
|
213
305
|
|
|
214
|
-
self = cls(1, 1)
|
|
215
306
|
|
|
216
|
-
self.number_of_rows = len(
|
|
307
|
+
self.number_of_rows = len(value)
|
|
217
308
|
self._number_of_columns = 0
|
|
218
309
|
|
|
219
|
-
for row, row_contents in enumerate(
|
|
220
|
-
for column,
|
|
221
|
-
if
|
|
222
|
-
self.dict[row, column] =
|
|
223
|
-
self._number_of_columns = max(self.number_of_columns, column)
|
|
224
|
-
|
|
310
|
+
for row, row_contents in enumerate(value, 1):
|
|
311
|
+
for column, item in enumerate(row_contents, 1):
|
|
312
|
+
if item is not None:
|
|
313
|
+
self.dict[row, column] = item
|
|
314
|
+
self._number_of_columns = max(self.number_of_columns, column)
|
|
315
|
+
|
|
225
316
|
|
|
226
317
|
def __setitem__(self, row_column, value):
|
|
227
318
|
row, column = row_column
|
|
@@ -238,14 +329,9 @@ class block:
|
|
|
238
329
|
if column < 1 or column > self.number_of_columns:
|
|
239
330
|
raise IndexError(f"column must be between 1 and {self.number_of_columns} not {column}")
|
|
240
331
|
return self.dict.get((row, column))
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
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)]
|
|
245
|
-
|
|
246
|
-
@property
|
|
247
|
-
def as_minimal_list_of_lists(self):
|
|
248
|
-
return [[self.dict.get((row, column)) for column in range(1, self.maximum_column + 1)] for row in range(1, self.maximum_row + 1)]
|
|
332
|
+
|
|
333
|
+
def minimized(self):
|
|
334
|
+
return block(self, number_of_rows=self.highest_used_row_number, number_of_columns=self.highest_used_column_number)
|
|
249
335
|
|
|
250
336
|
@property
|
|
251
337
|
def number_of_rows(self):
|
|
@@ -253,7 +339,7 @@ class block:
|
|
|
253
339
|
|
|
254
340
|
@number_of_rows.setter
|
|
255
341
|
def number_of_rows(self, value):
|
|
256
|
-
if value<1:
|
|
342
|
+
if value < 1:
|
|
257
343
|
raise ValueError(f"number_of_rows should be >=1, not {value}")
|
|
258
344
|
self._number_of_rows = value
|
|
259
345
|
for row, column in list(self.dict):
|
|
@@ -266,29 +352,30 @@ class block:
|
|
|
266
352
|
|
|
267
353
|
@number_of_columns.setter
|
|
268
354
|
def number_of_columns(self, value):
|
|
269
|
-
if value<1:
|
|
355
|
+
if value < 1:
|
|
270
356
|
raise ValueError(f"number_of_columns should be >=1, not {value}")
|
|
271
357
|
self._number_of_columns = value
|
|
272
358
|
for row, column in list(self.dict):
|
|
273
359
|
if column > self._number_of_columns:
|
|
274
360
|
del self.dict[row, column]
|
|
361
|
+
|
|
275
362
|
|
|
276
363
|
@property
|
|
277
|
-
def
|
|
364
|
+
def highest_used_row_number(self):
|
|
278
365
|
if self.dict:
|
|
279
366
|
return max(row for (row, column) in self.dict)
|
|
280
367
|
else:
|
|
281
368
|
return 1
|
|
282
369
|
|
|
283
370
|
@property
|
|
284
|
-
def
|
|
371
|
+
def highest_used_column_number(self):
|
|
285
372
|
if self.dict:
|
|
286
373
|
return max(column for (row, column) in self.dict)
|
|
287
374
|
else:
|
|
288
375
|
return 1
|
|
289
376
|
|
|
290
377
|
def __repr__(self):
|
|
291
|
-
return f"block
|
|
378
|
+
return f"block({self.value})"
|
|
292
379
|
|
|
293
380
|
|
|
294
381
|
def clear_captured_stdout():
|
|
@@ -300,7 +387,7 @@ def clear_captured_stdout():
|
|
|
300
387
|
|
|
301
388
|
def captured_stdout_as_str():
|
|
302
389
|
"""
|
|
303
|
-
returns the captured stdout as a
|
|
390
|
+
returns the captured stdout as a string
|
|
304
391
|
|
|
305
392
|
Returns
|
|
306
393
|
-------
|
|
@@ -311,7 +398,7 @@ def captured_stdout_as_str():
|
|
|
311
398
|
return "".join(_captured_stdout)
|
|
312
399
|
|
|
313
400
|
|
|
314
|
-
def
|
|
401
|
+
def captured_stdout_as_value():
|
|
315
402
|
"""
|
|
316
403
|
returns the captured stdout as a list of lists
|
|
317
404
|
|
|
@@ -319,14 +406,17 @@ def captured_stdout_as_list_of_lists():
|
|
|
319
406
|
-------
|
|
320
407
|
captured stdout : list
|
|
321
408
|
each line is an element of the list
|
|
322
|
-
"""
|
|
323
409
|
|
|
410
|
+
Note
|
|
411
|
+
----
|
|
412
|
+
This can be used directly to fill a xlwings range
|
|
413
|
+
"""
|
|
324
414
|
return [[line] for line in captured_stdout_as_str().splitlines()]
|
|
325
415
|
|
|
326
416
|
|
|
327
417
|
class capture_stdout:
|
|
328
418
|
"""
|
|
329
|
-
|
|
419
|
+
start capture stdout
|
|
330
420
|
|
|
331
421
|
Parameters
|
|
332
422
|
----------
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xlwings_utils
|
|
3
|
+
Version: 0.0.7
|
|
4
|
+
Summary: xlwings_utils
|
|
5
|
+
Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/salabim/xlwings_utils
|
|
7
|
+
Project-URL: Repository, https://github.com/salabim/xlwings_utils
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: dropbox
|
|
13
|
+
Requires-Dist: ssl
|
|
14
|
+
|
|
15
|
+
<img src="https://www.salabim.org/xlwings_utils_logo2.png">
|
|
16
|
+
|
|
17
|
+
## Introduction
|
|
18
|
+
|
|
19
|
+
This module provides some useful functions to be used in xlwings lite.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
Just add xlwings-utils to the *requirement.txt* tab. It might be required to add ssl.
|
|
24
|
+
|
|
25
|
+
In the script, add
|
|
26
|
+
|
|
27
|
+
```ìmport xlwings_utils as xwu```
|
|
28
|
+
|
|
29
|
+
## Dropbox support
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
It is only possible, as of now, to use full-access Dropbox apps.
|
|
34
|
+
|
|
35
|
+
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.
|
|
36
|
+
|
|
37
|
+
Then, it is possible to list all files in a specified folder with the function `list_dropbox`.
|
|
38
|
+
It is also possible to get the folders and to access all underlying folders.
|
|
39
|
+
|
|
40
|
+
The function `read_dropbox` can be used to read a Dropbox file's contents (bytes).
|
|
41
|
+
|
|
42
|
+
The function `write_dropbox` can be used to write contents (bytes) to a Dropbox file.
|
|
43
|
+
|
|
44
|
+
The functions `list_local`, `read_local` and `write_local` offer similar functionality for the local file system (on pyodide).
|
|
45
|
+
|
|
46
|
+
So, a way to access a file on the system's drive (mapped to Dropbox) as a local file is:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
contents = xlwings_utils.read_dropbox('/downloads/file1.xls')
|
|
50
|
+
xlwings_utils.write_local('file1.xlsx')
|
|
51
|
+
df = pandas.read_excel"file1.xlsx")
|
|
52
|
+
...
|
|
53
|
+
```
|
|
54
|
+
And the other direction:
|
|
55
|
+
```
|
|
56
|
+
contents = xlwings_utils.read_local('file1.gif')
|
|
57
|
+
xlwings_utils.write_dropbox('/downloads/file1.gif')
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Block support
|
|
61
|
+
|
|
62
|
+
The module contains a useful 2-dimensional data structure: *block*.
|
|
63
|
+
This can be useful to manipulate a range without accessing the range directly, which is expensive in terms of memory and execution time.
|
|
64
|
+
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.
|
|
65
|
+
So, `my_block(lol)[row, col]` is roughly equivalent to `lol[row-1][col-1]`
|
|
66
|
+
|
|
67
|
+
A block stores the values internally as a dictionary and will only convert these to a list of lists when using `block.value`.
|
|
68
|
+
|
|
69
|
+
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
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
my_block = xwu.block.from_value(range.value)
|
|
73
|
+
```
|
|
74
|
+
The dimensions (number of rows and number of columns) are automatically set.
|
|
75
|
+
|
|
76
|
+
Setting of an individual item (one-based, like range) can be done like
|
|
77
|
+
```
|
|
78
|
+
my_block[row, column] = x
|
|
79
|
+
```
|
|
80
|
+
And, likewise, reading an individual item can be done like
|
|
81
|
+
```
|
|
82
|
+
x = my_block[row, column]
|
|
83
|
+
```
|
|
84
|
+
It is not allowed t,o read or write outside the block dimensions.
|
|
85
|
+
|
|
86
|
+
It is also possible to define an empty block, like
|
|
87
|
+
```
|
|
88
|
+
block = xlwings_utils.block(number_of_rows, number_columns)
|
|
89
|
+
```
|
|
90
|
+
The dimensions can be queried or redefined with `block.number_of_rows` and
|
|
91
|
+
`block.number_of_columns`.
|
|
92
|
+
|
|
93
|
+
To assign a block to range, use
|
|
94
|
+
```
|
|
95
|
+
range.value = block.value
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The property `block.highest`_used_row_number returns the
|
|
99
|
+
|
|
100
|
+
The method `block.minimized()` returns a block that has the dimensions of (highest_used_row_number, highest_used_column_number).
|
|
101
|
+
|
|
102
|
+
## Capture stdout support
|
|
103
|
+
|
|
104
|
+
The module has support for capturing stdout and -later- using showing the captured output on a sheet.
|
|
105
|
+
|
|
106
|
+
To do that:
|
|
107
|
+
|
|
108
|
+
```makes it possible to capture stdout writes, which
|
|
109
|
+
with xwu.capture_stdout():
|
|
110
|
+
...
|
|
111
|
+
```
|
|
112
|
+
and then the captured output can be copied to the screen, like
|
|
113
|
+
|
|
114
|
+
```can then be copied to a worksheet in a later stage.
|
|
115
|
+
sheet.range(4,5).value = xwu.captured_stdout_as_value()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Clearing the captured stdout buffer can be done with `xwu.clear_captured_std_out`.
|
|
119
|
+
|
|
120
|
+
Normally, stdout will be also sent to the xlwings lite UI panel. This can be suppressed with
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
with xwu.capture_stdout(include_print=False):
|
|
124
|
+
...
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Badges
|
|
128
|
+
|
|
129
|
+
  
|
|
130
|
+
 
|
|
131
|
+

|
|
132
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
+
xlwings_utils/xlwings_utils.py,sha256=gCAgs3x6BjHaCX8I3HVw-s84EIS4pkrYQzCK38yG5T4,12656
|
|
3
|
+
xlwings_utils-0.0.7.dist-info/METADATA,sha256=js1Qw-rZuxDke_i-AjBl8P7mXZ7aMocqlJYj9Gfgyjg,4962
|
|
4
|
+
xlwings_utils-0.0.7.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
5
|
+
xlwings_utils-0.0.7.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
+
xlwings_utils-0.0.7.dist-info/RECORD,,
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: xlwings_utils
|
|
3
|
-
Version: 0.0.5
|
|
4
|
-
Summary: xlwings_utils
|
|
5
|
-
Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
|
|
6
|
-
Project-URL: Homepage, https://github.com/salabim/xlwings_utils
|
|
7
|
-
Project-URL: Repository, https://github.com/salabim/xlwings_utils
|
|
8
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
-
Requires-Python: >=3.9
|
|
11
|
-
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: dropbox
|
|
13
|
-
|
|
14
|
-
# xlwings_utils
|
|
15
|
-
|
|
16
|
-
## Introduction
|
|
17
|
-
|
|
18
|
-
This module provides some useful functions to be used in xlwings lite.
|
|
19
|
-
The xlwings lite system does not provide access to the local file system. With this
|
|
20
|
-
module, files can be copied between dropbox and the pyodide file systen. And
|
|
21
|
-
therefore, it is possible to indirectly use the local file system.
|
|
22
|
-
|
|
23
|
-
On top of that, this module makes it possible to capture stdout writes, which
|
|
24
|
-
can then be copied to a worksheet in a later stage.
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
Just add xlwings-utils to the requirement tab.
|
|
29
|
-
|
|
30
|
-
## Dropbox support
|
|
31
|
-
|
|
32
|
-
xlwings_lite only works with full access dropbox apps.
|
|
33
|
-
|
|
34
|
-
In order to use dropbox, is is necessary to initialize the module with credentials.
|
|
35
|
-
|
|
36
|
-
## Capture stdout support
|
|
37
|
-
|
|
38
|
-
Badges
|
|
39
|
-
|
|
40
|
-
  
|
|
41
|
-
 
|
|
42
|
-

|
|
43
|
-
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
xlwings_utils/__init__.py,sha256=FdaRztevSu5akGL7KBUBRzqwLMRTdvVUuS2Kfp2f1Uc,68
|
|
2
|
-
xlwings_utils/xlwings_utils.py,sha256=RiDWmEsUQclIjB5fYofA9D4WRIp3qQLMFq5-vEkOJ4E,9508
|
|
3
|
-
xlwings_utils-0.0.5.dist-info/METADATA,sha256=XiPrWlKI2a683dGVOa7FMBsYt5SqOhGe8cu7FTQDU1w,1662
|
|
4
|
-
xlwings_utils-0.0.5.dist-info/WHEEL,sha256=GHB6lJx2juba1wDgXDNlMTyM13ckjBMKf-OnwgKOCtA,91
|
|
5
|
-
xlwings_utils-0.0.5.dist-info/top_level.txt,sha256=kf5SEv0gZiRObPhUoYcc1O_iX_wwTOPeUIYvzyYeAM4,14
|
|
6
|
-
xlwings_utils-0.0.5.dist-info/RECORD,,
|
|
File without changes
|