tdrpa.tdworker 1.2.13.2__py312-none-win_amd64.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.
- tdrpa/_tdxlwings/__init__.py +193 -0
- tdrpa/_tdxlwings/__pycache__/__init__.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/__init__.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/apps.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/apps.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/base_classes.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/base_classes.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/com_server.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/com_server.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/constants.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/constants.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/expansion.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/expansion.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/main.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/main.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/udfs.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/udfs.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/utils.cpython-311.pyc +0 -0
- tdrpa/_tdxlwings/__pycache__/utils.cpython-38.pyc +0 -0
- tdrpa/_tdxlwings/_win32patch.py +90 -0
- tdrpa/_tdxlwings/_xlmac.py +2240 -0
- tdrpa/_tdxlwings/_xlwindows.py +2518 -0
- tdrpa/_tdxlwings/addin/Dictionary.cls +474 -0
- tdrpa/_tdxlwings/addin/IWebAuthenticator.cls +71 -0
- tdrpa/_tdxlwings/addin/WebClient.cls +772 -0
- tdrpa/_tdxlwings/addin/WebHelpers.bas +3203 -0
- tdrpa/_tdxlwings/addin/WebRequest.cls +875 -0
- tdrpa/_tdxlwings/addin/WebResponse.cls +453 -0
- tdrpa/_tdxlwings/addin/xlwings.xlam +0 -0
- tdrpa/_tdxlwings/apps.py +35 -0
- tdrpa/_tdxlwings/base_classes.py +1092 -0
- tdrpa/_tdxlwings/cli.py +1306 -0
- tdrpa/_tdxlwings/com_server.py +385 -0
- tdrpa/_tdxlwings/constants.py +3080 -0
- tdrpa/_tdxlwings/conversion/__init__.py +103 -0
- tdrpa/_tdxlwings/conversion/framework.py +147 -0
- tdrpa/_tdxlwings/conversion/numpy_conv.py +34 -0
- tdrpa/_tdxlwings/conversion/pandas_conv.py +184 -0
- tdrpa/_tdxlwings/conversion/standard.py +321 -0
- tdrpa/_tdxlwings/expansion.py +83 -0
- tdrpa/_tdxlwings/ext/__init__.py +3 -0
- tdrpa/_tdxlwings/ext/sql.py +73 -0
- tdrpa/_tdxlwings/html/xlwings-alert.html +71 -0
- tdrpa/_tdxlwings/js/xlwings.js +577 -0
- tdrpa/_tdxlwings/js/xlwings.ts +729 -0
- tdrpa/_tdxlwings/mac_dict.py +6399 -0
- tdrpa/_tdxlwings/main.py +5205 -0
- tdrpa/_tdxlwings/mistune/__init__.py +63 -0
- tdrpa/_tdxlwings/mistune/block_parser.py +366 -0
- tdrpa/_tdxlwings/mistune/inline_parser.py +216 -0
- tdrpa/_tdxlwings/mistune/markdown.py +84 -0
- tdrpa/_tdxlwings/mistune/renderers.py +220 -0
- tdrpa/_tdxlwings/mistune/scanner.py +121 -0
- tdrpa/_tdxlwings/mistune/util.py +41 -0
- tdrpa/_tdxlwings/pro/__init__.py +40 -0
- tdrpa/_tdxlwings/pro/_xlcalamine.py +536 -0
- tdrpa/_tdxlwings/pro/_xlofficejs.py +146 -0
- tdrpa/_tdxlwings/pro/_xlremote.py +1293 -0
- tdrpa/_tdxlwings/pro/custom_functions_code.js +150 -0
- tdrpa/_tdxlwings/pro/embedded_code.py +60 -0
- tdrpa/_tdxlwings/pro/udfs_officejs.py +549 -0
- tdrpa/_tdxlwings/pro/utils.py +199 -0
- tdrpa/_tdxlwings/quickstart.xlsm +0 -0
- tdrpa/_tdxlwings/quickstart_addin.xlam +0 -0
- tdrpa/_tdxlwings/quickstart_addin_ribbon.xlam +0 -0
- tdrpa/_tdxlwings/quickstart_fastapi/main.py +47 -0
- tdrpa/_tdxlwings/quickstart_fastapi/requirements.txt +3 -0
- tdrpa/_tdxlwings/quickstart_standalone.xlsm +0 -0
- tdrpa/_tdxlwings/reports.py +12 -0
- tdrpa/_tdxlwings/rest/__init__.py +1 -0
- tdrpa/_tdxlwings/rest/api.py +368 -0
- tdrpa/_tdxlwings/rest/serializers.py +103 -0
- tdrpa/_tdxlwings/server.py +14 -0
- tdrpa/_tdxlwings/udfs.py +775 -0
- tdrpa/_tdxlwings/utils.py +777 -0
- tdrpa/_tdxlwings/xlwings-0.31.6.applescript +30 -0
- tdrpa/_tdxlwings/xlwings.bas +2061 -0
- tdrpa/_tdxlwings/xlwings_custom_addin.bas +2042 -0
- tdrpa/_tdxlwings/xlwingslib.cp38-win_amd64.pyd +0 -0
- tdrpa/tdworker/__init__.pyi +12 -0
- tdrpa/tdworker/_clip.pyi +50 -0
- tdrpa/tdworker/_excel.pyi +743 -0
- tdrpa/tdworker/_file.pyi +77 -0
- tdrpa/tdworker/_img.pyi +226 -0
- tdrpa/tdworker/_network.pyi +94 -0
- tdrpa/tdworker/_os.pyi +47 -0
- tdrpa/tdworker/_sp.pyi +21 -0
- tdrpa/tdworker/_w.pyi +129 -0
- tdrpa/tdworker/_web.pyi +995 -0
- tdrpa/tdworker/_winE.pyi +228 -0
- tdrpa/tdworker/_winK.pyi +74 -0
- tdrpa/tdworker/_winM.pyi +117 -0
- tdrpa/tdworker.cp312-win_amd64.pyd +0 -0
- tdrpa_tdworker-1.2.13.2.dist-info/METADATA +38 -0
- tdrpa_tdworker-1.2.13.2.dist-info/RECORD +101 -0
- tdrpa_tdworker-1.2.13.2.dist-info/WHEEL +5 -0
- tdrpa_tdworker-1.2.13.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,321 @@
|
|
1
|
+
import datetime
|
2
|
+
import math
|
3
|
+
from collections import OrderedDict
|
4
|
+
|
5
|
+
from .. import LicenseError
|
6
|
+
from ..main import Range
|
7
|
+
from ..utils import chunk, xlserial_to_datetime
|
8
|
+
from . import Accessor, Converter, Options, Pipeline, accessors
|
9
|
+
|
10
|
+
try:
|
11
|
+
from ..pro import Markdown
|
12
|
+
from ..pro.reports import markdown
|
13
|
+
except (ImportError, LicenseError, AttributeError):
|
14
|
+
Markdown = None
|
15
|
+
try:
|
16
|
+
import numpy as np
|
17
|
+
except ImportError:
|
18
|
+
np = None
|
19
|
+
|
20
|
+
|
21
|
+
_date_handlers = {
|
22
|
+
datetime.datetime: datetime.datetime,
|
23
|
+
datetime.date: lambda year, month, day, **kwargs: datetime.date(year, month, day),
|
24
|
+
}
|
25
|
+
|
26
|
+
_number_handlers = {
|
27
|
+
int: lambda x: int(round(x)),
|
28
|
+
"raw int": int,
|
29
|
+
}
|
30
|
+
|
31
|
+
|
32
|
+
class ExpandRangeStage:
|
33
|
+
def __init__(self, options):
|
34
|
+
self.expand = options.get("expand", None)
|
35
|
+
|
36
|
+
def __call__(self, c):
|
37
|
+
if c.range:
|
38
|
+
# auto-expand the range
|
39
|
+
if self.expand:
|
40
|
+
c.range = c.range.expand(self.expand)
|
41
|
+
|
42
|
+
|
43
|
+
class WriteValueToRangeStage:
|
44
|
+
def __init__(self, options, raw=False):
|
45
|
+
self.raw = raw
|
46
|
+
self.options = options
|
47
|
+
|
48
|
+
def _write_value(self, rng, value, scalar):
|
49
|
+
if rng.api and value:
|
50
|
+
# it is assumed by this stage that value is a list of lists
|
51
|
+
if scalar:
|
52
|
+
value = value[0][0]
|
53
|
+
else:
|
54
|
+
rng = rng.resize(len(value), len(value[0]))
|
55
|
+
|
56
|
+
chunksize = self.options.get("chunksize")
|
57
|
+
if chunksize:
|
58
|
+
for ix, value_chunk in enumerate(chunk(value, chunksize)):
|
59
|
+
rng[
|
60
|
+
ix * chunksize : ix * chunksize + chunksize, :
|
61
|
+
].raw_value = value_chunk
|
62
|
+
else:
|
63
|
+
rng.raw_value = value
|
64
|
+
|
65
|
+
def __call__(self, ctx):
|
66
|
+
if ctx.range and ctx.value:
|
67
|
+
if self.raw:
|
68
|
+
ctx.range.raw_value = ctx.value
|
69
|
+
return
|
70
|
+
|
71
|
+
scalar = ctx.meta.get("scalar", False)
|
72
|
+
if not scalar:
|
73
|
+
ctx.range = ctx.range.resize(len(ctx.value), len(ctx.value[0]))
|
74
|
+
|
75
|
+
self._write_value(ctx.range, ctx.value, scalar)
|
76
|
+
|
77
|
+
|
78
|
+
class ReadValueFromRangeStage:
|
79
|
+
def __init__(self, options):
|
80
|
+
self.options = options
|
81
|
+
|
82
|
+
def __call__(self, c):
|
83
|
+
chunksize = self.options.get("chunksize")
|
84
|
+
if c.range and chunksize:
|
85
|
+
parts = []
|
86
|
+
for i in range(math.ceil(c.range.shape[0] / chunksize)):
|
87
|
+
raw_value = c.range[
|
88
|
+
i * chunksize : (i * chunksize) + chunksize, :
|
89
|
+
].raw_value
|
90
|
+
if isinstance(raw_value[0], (list, tuple)):
|
91
|
+
parts.extend(raw_value)
|
92
|
+
else:
|
93
|
+
# Turn a single row list into a 2d list
|
94
|
+
parts.extend([raw_value])
|
95
|
+
|
96
|
+
c.value = parts
|
97
|
+
elif c.range:
|
98
|
+
c.value = c.range.raw_value
|
99
|
+
|
100
|
+
|
101
|
+
class CleanDataFromReadStage:
|
102
|
+
def __init__(self, options):
|
103
|
+
self.options = options
|
104
|
+
dates_as = options.get("dates", datetime.datetime)
|
105
|
+
self.empty_as = options.get("empty", None)
|
106
|
+
self.dates_handler = _date_handlers.get(dates_as, dates_as)
|
107
|
+
numbers_as = options.get("numbers", None)
|
108
|
+
self.numbers_handler = _number_handlers.get(numbers_as, numbers_as)
|
109
|
+
self.err_to_str = options.get("err_to_str", False)
|
110
|
+
|
111
|
+
def __call__(self, c):
|
112
|
+
c.value = c.engine.impl.clean_value_data(
|
113
|
+
c.value,
|
114
|
+
self.dates_handler,
|
115
|
+
self.empty_as,
|
116
|
+
self.numbers_handler,
|
117
|
+
self.err_to_str,
|
118
|
+
)
|
119
|
+
|
120
|
+
|
121
|
+
class CleanDataForWriteStage:
|
122
|
+
def __init__(self, options):
|
123
|
+
self.options = options
|
124
|
+
|
125
|
+
def __call__(self, c):
|
126
|
+
c.value = [
|
127
|
+
[c.engine.impl.prepare_xl_data_element(x, self.options) for x in y]
|
128
|
+
for y in c.value
|
129
|
+
]
|
130
|
+
|
131
|
+
|
132
|
+
class AdjustDimensionsStage:
|
133
|
+
def __init__(self, options):
|
134
|
+
self.ndim = options.get("ndim", None)
|
135
|
+
|
136
|
+
def __call__(self, c):
|
137
|
+
# the assumption is that value is 2-dimensional at this stage
|
138
|
+
|
139
|
+
if self.ndim is None:
|
140
|
+
if len(c.value) == 1:
|
141
|
+
c.value = c.value[0][0] if len(c.value[0]) == 1 else c.value[0]
|
142
|
+
elif len(c.value[0]) == 1:
|
143
|
+
c.value = [x[0] for x in c.value]
|
144
|
+
else:
|
145
|
+
c.value = c.value
|
146
|
+
|
147
|
+
elif self.ndim == 1:
|
148
|
+
if len(c.value) == 1:
|
149
|
+
c.value = c.value[0]
|
150
|
+
elif len(c.value[0]) == 1:
|
151
|
+
c.value = [x[0] for x in c.value]
|
152
|
+
else:
|
153
|
+
raise Exception("Range must be 1-by-n or n-by-1 when ndim=1.")
|
154
|
+
|
155
|
+
# ndim = 2 is a no-op
|
156
|
+
elif self.ndim != 2:
|
157
|
+
raise ValueError("Invalid c.value ndim=%s" % self.ndim)
|
158
|
+
|
159
|
+
|
160
|
+
class Ensure2DStage:
|
161
|
+
def __call__(self, c):
|
162
|
+
if isinstance(c.value, (list, tuple)):
|
163
|
+
if len(c.value) > 0:
|
164
|
+
if not isinstance(c.value[0], (list, tuple)):
|
165
|
+
c.value = [c.value]
|
166
|
+
else:
|
167
|
+
c.meta["scalar"] = True
|
168
|
+
c.value = [[c.value]]
|
169
|
+
|
170
|
+
|
171
|
+
class TransposeStage:
|
172
|
+
def __call__(self, c):
|
173
|
+
c.value = [
|
174
|
+
[e[i] for e in c.value] for i in range(len(c.value[0]) if c.value else 0)
|
175
|
+
]
|
176
|
+
|
177
|
+
|
178
|
+
class FormatStage:
|
179
|
+
def __init__(self, options):
|
180
|
+
self.options = options
|
181
|
+
|
182
|
+
def __call__(self, ctx):
|
183
|
+
if Markdown and isinstance(ctx.source_value, Markdown):
|
184
|
+
markdown.format_text(
|
185
|
+
ctx.range, ctx.source_value.text, ctx.source_value.style
|
186
|
+
)
|
187
|
+
if "formatter" in self.options:
|
188
|
+
self.options["formatter"](ctx.range, ctx.source_value)
|
189
|
+
|
190
|
+
|
191
|
+
class BaseAccessor(Accessor):
|
192
|
+
@classmethod
|
193
|
+
def reader(cls, options):
|
194
|
+
return Pipeline().append_stage(
|
195
|
+
ExpandRangeStage(options), only_if=options.get("expand", None)
|
196
|
+
)
|
197
|
+
|
198
|
+
|
199
|
+
class RangeAccessor(Accessor):
|
200
|
+
@staticmethod
|
201
|
+
def copy_range_to_value(c):
|
202
|
+
c.value = c.range
|
203
|
+
|
204
|
+
@classmethod
|
205
|
+
def reader(cls, options):
|
206
|
+
return BaseAccessor.reader(options).append_stage(
|
207
|
+
RangeAccessor.copy_range_to_value
|
208
|
+
)
|
209
|
+
|
210
|
+
|
211
|
+
RangeAccessor.register("range", Range)
|
212
|
+
|
213
|
+
|
214
|
+
class RawValueAccessor(Accessor):
|
215
|
+
@classmethod
|
216
|
+
def reader(cls, options):
|
217
|
+
return Accessor.reader(options).append_stage(ReadValueFromRangeStage(options))
|
218
|
+
|
219
|
+
@classmethod
|
220
|
+
def writer(cls, options):
|
221
|
+
return Accessor.writer(options).prepend_stage(
|
222
|
+
WriteValueToRangeStage(options, raw=True)
|
223
|
+
)
|
224
|
+
|
225
|
+
|
226
|
+
RawValueAccessor.register("raw")
|
227
|
+
|
228
|
+
|
229
|
+
class ValueAccessor(Accessor):
|
230
|
+
@staticmethod
|
231
|
+
def reader(options):
|
232
|
+
return (
|
233
|
+
BaseAccessor.reader(options)
|
234
|
+
.append_stage(ReadValueFromRangeStage(options))
|
235
|
+
.append_stage(Ensure2DStage())
|
236
|
+
.append_stage(CleanDataFromReadStage(options))
|
237
|
+
.append_stage(TransposeStage(), only_if=options.get("transpose", False))
|
238
|
+
.append_stage(AdjustDimensionsStage(options))
|
239
|
+
)
|
240
|
+
|
241
|
+
@staticmethod
|
242
|
+
def writer(options):
|
243
|
+
return (
|
244
|
+
Pipeline()
|
245
|
+
.prepend_stage(FormatStage(options))
|
246
|
+
.prepend_stage(WriteValueToRangeStage(options))
|
247
|
+
.prepend_stage(CleanDataForWriteStage(options))
|
248
|
+
.prepend_stage(TransposeStage(), only_if=options.get("transpose", False))
|
249
|
+
.prepend_stage(Ensure2DStage())
|
250
|
+
)
|
251
|
+
|
252
|
+
@classmethod
|
253
|
+
def router(cls, value, rng, options):
|
254
|
+
return accessors.get(type(value), cls)
|
255
|
+
|
256
|
+
|
257
|
+
ValueAccessor.register(None)
|
258
|
+
|
259
|
+
|
260
|
+
class DictConverter(Converter):
|
261
|
+
@classmethod
|
262
|
+
def base_reader(cls, options):
|
263
|
+
return super(DictConverter, cls).base_reader(Options(options).override(ndim=2))
|
264
|
+
|
265
|
+
@classmethod
|
266
|
+
def read_value(cls, value, options):
|
267
|
+
assert not value or len(value[0]) == 2
|
268
|
+
return dict(value)
|
269
|
+
|
270
|
+
@classmethod
|
271
|
+
def write_value(cls, value, options):
|
272
|
+
return list(value.items())
|
273
|
+
|
274
|
+
|
275
|
+
DictConverter.register(dict)
|
276
|
+
|
277
|
+
|
278
|
+
class OrderedDictConverter(Converter):
|
279
|
+
@classmethod
|
280
|
+
def base_reader(cls, options):
|
281
|
+
return super(OrderedDictConverter, cls).base_reader(
|
282
|
+
Options(options).override(ndim=2)
|
283
|
+
)
|
284
|
+
|
285
|
+
@classmethod
|
286
|
+
def read_value(cls, value, options):
|
287
|
+
assert not value or len(value[0]) == 2
|
288
|
+
return OrderedDict(value)
|
289
|
+
|
290
|
+
@classmethod
|
291
|
+
def write_value(cls, value, options):
|
292
|
+
return list(value.items())
|
293
|
+
|
294
|
+
|
295
|
+
OrderedDictConverter.register(OrderedDict)
|
296
|
+
|
297
|
+
|
298
|
+
class DatetimeConverter(Converter):
|
299
|
+
@classmethod
|
300
|
+
def read_value(cls, value, options):
|
301
|
+
return xlserial_to_datetime(value)
|
302
|
+
|
303
|
+
@classmethod
|
304
|
+
def write_value(cls, value, options):
|
305
|
+
return value
|
306
|
+
|
307
|
+
|
308
|
+
DatetimeConverter.register(datetime.datetime)
|
309
|
+
|
310
|
+
|
311
|
+
class DateConverter(Converter):
|
312
|
+
@classmethod
|
313
|
+
def read_value(cls, value, options):
|
314
|
+
return xlserial_to_datetime(value).date()
|
315
|
+
|
316
|
+
@classmethod
|
317
|
+
def write_value(cls, value, options):
|
318
|
+
return value
|
319
|
+
|
320
|
+
|
321
|
+
DateConverter.register(datetime.date)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from .main import Range
|
2
|
+
|
3
|
+
expanders = {}
|
4
|
+
|
5
|
+
_empty = (None, "", [[""]], [[None]], [("",)], [(None,)])
|
6
|
+
|
7
|
+
|
8
|
+
class Expander:
|
9
|
+
def register(self, *aliases):
|
10
|
+
for alias in aliases:
|
11
|
+
expanders[alias] = self
|
12
|
+
|
13
|
+
def expand(self, rng):
|
14
|
+
"""
|
15
|
+
Expands a range
|
16
|
+
|
17
|
+
Arguments
|
18
|
+
---------
|
19
|
+
rng: Range
|
20
|
+
The reference range
|
21
|
+
|
22
|
+
Returns
|
23
|
+
-------
|
24
|
+
Range object: The expanded range
|
25
|
+
|
26
|
+
"""
|
27
|
+
raise NotImplementedError()
|
28
|
+
|
29
|
+
|
30
|
+
class TableExpander(Expander):
|
31
|
+
def expand(self, rng):
|
32
|
+
origin = rng(1, 1)
|
33
|
+
|
34
|
+
if origin.has_array:
|
35
|
+
bottom_left = origin.end("down")
|
36
|
+
elif origin(2, 1).raw_value in _empty:
|
37
|
+
bottom_left = origin
|
38
|
+
elif origin(3, 1).raw_value in _empty:
|
39
|
+
bottom_left = origin(2, 1)
|
40
|
+
else:
|
41
|
+
bottom_left = origin(2, 1).end("down")
|
42
|
+
|
43
|
+
if origin.has_array:
|
44
|
+
top_right = origin.end("right")
|
45
|
+
elif origin(1, 2).raw_value in _empty:
|
46
|
+
top_right = origin
|
47
|
+
elif origin(1, 3).raw_value in _empty:
|
48
|
+
top_right = origin(1, 2)
|
49
|
+
else:
|
50
|
+
top_right = origin(1, 2).end("right")
|
51
|
+
|
52
|
+
return Range(top_right, bottom_left)
|
53
|
+
|
54
|
+
|
55
|
+
TableExpander().register("table")
|
56
|
+
|
57
|
+
|
58
|
+
class VerticalExpander(Expander):
|
59
|
+
def expand(self, rng):
|
60
|
+
if rng(2, 1).raw_value in _empty:
|
61
|
+
return Range(rng(1, 1), rng(1, rng.shape[1]))
|
62
|
+
elif rng(3, 1).raw_value in _empty:
|
63
|
+
return Range(rng(1, 1), rng(2, rng.shape[1]))
|
64
|
+
else:
|
65
|
+
end_row = rng(2, 1).end("down").row - rng.row + 1
|
66
|
+
return Range(rng(1, 1), rng(end_row, rng.shape[1]))
|
67
|
+
|
68
|
+
|
69
|
+
VerticalExpander().register("vertical", "down", "d")
|
70
|
+
|
71
|
+
|
72
|
+
class HorizontalExpander(Expander):
|
73
|
+
def expand(self, rng):
|
74
|
+
if rng(1, 2).raw_value in _empty:
|
75
|
+
return Range(rng(1, 1), rng(rng.shape[0], 1))
|
76
|
+
elif rng(1, 3).raw_value in _empty:
|
77
|
+
return Range(rng(1, 1), rng(rng.shape[0], 2))
|
78
|
+
else:
|
79
|
+
end_column = rng(1, 2).end("right").column - rng.column + 1
|
80
|
+
return Range(rng(1, 1), rng(rng.shape[0], end_column))
|
81
|
+
|
82
|
+
|
83
|
+
HorizontalExpander().register("horizontal", "right", "r")
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import sqlite3
|
2
|
+
|
3
|
+
from .. import arg, func, ret
|
4
|
+
|
5
|
+
|
6
|
+
def conv_value(value, col_is_str):
|
7
|
+
if value is None:
|
8
|
+
return "NULL"
|
9
|
+
if col_is_str:
|
10
|
+
return repr(str(value))
|
11
|
+
elif isinstance(value, bool):
|
12
|
+
return 1 if value else 0
|
13
|
+
else:
|
14
|
+
return repr(value)
|
15
|
+
|
16
|
+
|
17
|
+
@func
|
18
|
+
@arg("tables", expand="table", ndim=2)
|
19
|
+
@ret(expand="table")
|
20
|
+
def sql(query, *tables):
|
21
|
+
return _sql(query, *tables)
|
22
|
+
|
23
|
+
|
24
|
+
@func
|
25
|
+
@arg("tables", expand="table", ndim=2)
|
26
|
+
def sql_dynamic(query, *tables):
|
27
|
+
"""Called if native dynamic arrays are available"""
|
28
|
+
return _sql(query, *tables)
|
29
|
+
|
30
|
+
|
31
|
+
def _sql(query, *tables):
|
32
|
+
conn = sqlite3.connect(":memory:")
|
33
|
+
|
34
|
+
c = conn.cursor()
|
35
|
+
|
36
|
+
for i, table in enumerate(tables):
|
37
|
+
cols = table[0]
|
38
|
+
rows = table[1:]
|
39
|
+
types = [any(isinstance(row[j], str) for row in rows) for j in range(len(cols))]
|
40
|
+
name = chr(65 + i)
|
41
|
+
|
42
|
+
stmt = "CREATE TABLE %s (%s)" % (
|
43
|
+
name,
|
44
|
+
", ".join(
|
45
|
+
"'%s' %s" % (col, "STRING" if typ else "REAL")
|
46
|
+
for col, typ in zip(cols, types)
|
47
|
+
),
|
48
|
+
)
|
49
|
+
c.execute(stmt)
|
50
|
+
|
51
|
+
if rows:
|
52
|
+
stmt = "INSERT INTO %s VALUES %s" % (
|
53
|
+
name,
|
54
|
+
", ".join(
|
55
|
+
"(%s)"
|
56
|
+
% ", ".join(
|
57
|
+
conv_value(value, type) for value, typ in zip(row, types)
|
58
|
+
)
|
59
|
+
for row in rows
|
60
|
+
),
|
61
|
+
)
|
62
|
+
# Fixes values like these:
|
63
|
+
# sql('SELECT a FROM a', [['a', 'b'], ["""X"Y'Z""", 'd']])
|
64
|
+
stmt = stmt.replace("\\'", "''")
|
65
|
+
c.execute(stmt)
|
66
|
+
|
67
|
+
res = []
|
68
|
+
c.execute(query)
|
69
|
+
res.append([x[0] for x in c.description])
|
70
|
+
for row in c:
|
71
|
+
res.append(list(row))
|
72
|
+
|
73
|
+
return res
|
@@ -0,0 +1,71 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<!--
|
3
|
+
Copyright (C) 2014 - present, Zoomer Analytics GmbH. All rights reserved.
|
4
|
+
Licensed under BSD-3-Clause license, see: https://docs.xlwings.org/en/stable/license.html
|
5
|
+
|
6
|
+
This file also contains code from Bootstrap
|
7
|
+
Copyright (c) 2011-2023 The Bootstrap Authors, Licensed under MIT license, see https://raw.githubusercontent.com/twbs/bootstrap/main/LICENSE
|
8
|
+
|
9
|
+
This file also contains code from bootstrap-ie11
|
10
|
+
Copyright (c) 2022 Christian Oliff, Licensed under MIT license, see https://raw.githubusercontent.com/coliff/bootstrap-ie11/main/LICENSE
|
11
|
+
-->
|
12
|
+
<html lang="en">
|
13
|
+
|
14
|
+
<head>
|
15
|
+
<meta charset="utf-8">
|
16
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
17
|
+
<title>Alert</title>
|
18
|
+
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
19
|
+
<link rel="stylesheet"
|
20
|
+
href="https://cdn.jsdelivr.net/gh/xlwings/bootstrap-xlwings@5.2.3-2/dist/bootstrap-xlwings.min.css"
|
21
|
+
integrity="sha384-TZ8CaOSXLBEEL73Aw1vX6a/2YP7QHdiuilF2C8Put8X81F3FzyRgt9ba77CMKAXq" crossorigin="anonymous">
|
22
|
+
<script
|
23
|
+
nomodule>window.MSInputMethodContext && document.documentMode && document.write('<link rel="stylesheet" href="/css/bootstrap-ie11.min.css"><script src="https://cdn.jsdelivr.net/combine/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js,npm/ie11-custom-properties@4,npm/element-qsa-scope@1"><\/script><script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=default%2CNumber.parseInt%2CNumber.parseFloat%2CArray.prototype.find%2CArray.prototype.includes"><\/script>');</script>
|
24
|
+
</head>
|
25
|
+
|
26
|
+
<body>
|
27
|
+
<div id="callback" data-callback="{{ callback }}"></div>
|
28
|
+
<div class="container-fluid">
|
29
|
+
<div class="d-flex flex-column pb-3 px-2 vh-100">
|
30
|
+
<h1 class="pt-4">{{ title }}</h1>
|
31
|
+
<p>{{ prompt|replace("\n", "<br>"|safe) }}</p>
|
32
|
+
<div class="mt-auto">
|
33
|
+
<div class="float-end">
|
34
|
+
{% if "ok" in buttons %}
|
35
|
+
<button id="ok" type="button" class="btn btn-primary btn-xl-alert">OK</button>
|
36
|
+
{% endif %}
|
37
|
+
{% if "yes" in buttons %}
|
38
|
+
<button id="yes" type="button" class="btn btn-primary btn-xl-alert">Yes</button>
|
39
|
+
{% endif %}
|
40
|
+
{% if "no" in buttons %}
|
41
|
+
<button id="no" type="button" class="btn btn-outline-secondary btn-xl-alert">No</button>
|
42
|
+
{% endif %}
|
43
|
+
{% if "cancel" in buttons %}
|
44
|
+
<button id="cancel" type="button" class="btn btn-outline-secondary btn-xl-alert">Cancel</button>
|
45
|
+
{% endif %}
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
|
51
|
+
<script>
|
52
|
+
Office.onReady(function (info) { });
|
53
|
+
if (document.getElementById("ok")) {
|
54
|
+
document.getElementById("ok").addEventListener("click", buttonCallback);
|
55
|
+
}
|
56
|
+
if (document.getElementById("yes")) {
|
57
|
+
document.getElementById("yes").addEventListener("click", buttonCallback);
|
58
|
+
}
|
59
|
+
if (document.getElementById("no")) {
|
60
|
+
document.getElementById("no").addEventListener("click", buttonCallback);
|
61
|
+
}
|
62
|
+
if (document.getElementById("cancel")) {
|
63
|
+
document.getElementById("cancel").addEventListener("click", buttonCallback);
|
64
|
+
}
|
65
|
+
function buttonCallback() {
|
66
|
+
Office.context.ui.messageParent(this.id + "|" + document.getElementById("callback").getAttribute("data-callback"));
|
67
|
+
}
|
68
|
+
</script>
|
69
|
+
</body>
|
70
|
+
|
71
|
+
</html>
|