pyOpenVBA 5.2.1__tar.gz → 5.2.2__tar.gz
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.
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/PKG-INFO +1 -1
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/power_query.md +7 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/pyproject.toml +1 -1
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/__init__.py +1 -1
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_sheets.py +40 -9
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/.gitignore +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/LICENSE.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/architecture.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/ms-ovba-implementation-guide_v2.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/research/access_complex/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/research/access_designs/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/research/access_macros/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/research/access_write/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/research/pcode/README.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/docs/roadmap.md +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/__main__.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_deflate.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_host.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_oforms_pages.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_oforms_records.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_ppt_container.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/__init__.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_database.accdb +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_database_module.accdb +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_document.docm +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_excel_addin.xlam +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_presentation.pptm +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsb +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsm +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsx +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/engine_skeleton.accdb +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/engine_skeleton.mdb +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/form.blob +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/form.lvprop +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/form.propdata +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/form.prototypes +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/form.typeinfo +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/report.blob +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/report.lvprop +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/report.propdata +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/report.prototypes +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/designs/report.typeinfo +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/__init__.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_alloc.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_btree.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_collation.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_collation_general_legacy.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_compact.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_complex.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_datapage.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_ddl.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_designs.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_facade.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_format.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_index.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_lval.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_macros.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_pages.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_props.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_queries.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_rows.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_schema.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_sql.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_storage.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_tdef.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_validate.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/_vba.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access/database.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/access_read.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/cfb.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/excel.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/exceptions.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/forms.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerpoint.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/__init__.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_binary.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_files.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_mashup.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_metadata.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_opc.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_package.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_refresh.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/_section.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/powerquery/workbook.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/vba.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/vba_pcode.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/word.py +0 -0
- {pyopenvba-5.2.1 → pyopenvba-5.2.2}/tests/fuzz_corpus/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pyOpenVBA
|
|
3
|
-
Version: 5.2.
|
|
3
|
+
Version: 5.2.2
|
|
4
4
|
Summary: Read and write VBA macros and Excel Power Query in pure Python, no dependencies.
|
|
5
5
|
Project-URL: Homepage, https://github.com/WilliamSmithEdward/pyOpenVBA
|
|
6
6
|
Project-URL: Repository, https://github.com/WilliamSmithEdward/pyOpenVBA
|
|
@@ -221,6 +221,13 @@ wrong: **a connections part holding no connections is one Excel refuses**,
|
|
|
221
221
|
so removing the last connection removes the part, its content type and
|
|
222
222
|
its relationship as well.
|
|
223
223
|
|
|
224
|
+
The hidden name has a rule of its own. **`localSheetId` is the zero-based
|
|
225
|
+
position of the sheet the name belongs to** among the workbook's sheets,
|
|
226
|
+
not a constant, and it has to agree with the sheet the reference names.
|
|
227
|
+
Written as 0 it was right only while the table landed on the first sheet;
|
|
228
|
+
anywhere else Excel refuses to open the workbook, which is invisible in a
|
|
229
|
+
one-sheet file and so went unnoticed.
|
|
230
|
+
|
|
224
231
|
### Refresh control
|
|
225
232
|
|
|
226
233
|
The boxes in Excel's Connection Properties dialog belong to that
|
|
@@ -169,13 +169,15 @@ def drop_content_type(package: OpcFile, part: str) -> None:
|
|
|
169
169
|
)
|
|
170
170
|
|
|
171
171
|
|
|
172
|
-
def
|
|
173
|
-
"""
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
172
|
+
def sheet_entries(workbook: str) -> list[tuple[str, str]]:
|
|
173
|
+
"""``(name, relationship id)`` for each sheet, in the order the
|
|
174
|
+
workbook lists them.
|
|
175
|
+
|
|
176
|
+
The order is load-bearing: a ``definedName`` names the sheet it is
|
|
177
|
+
local to by its position here, so the list is the one place that
|
|
178
|
+
settles both which part a sheet is and what index it has.
|
|
179
|
+
"""
|
|
180
|
+
out: list[tuple[str, str]] = []
|
|
179
181
|
for element in re.findall(r"<sheet\b[^>]*>", workbook):
|
|
180
182
|
attributes = _attributes(element)
|
|
181
183
|
# The relationship attribute carries a namespace prefix, and which
|
|
@@ -184,7 +186,27 @@ def sheet_part(package: OpcFile, sheet: str | int) -> tuple[str, str]:
|
|
|
184
186
|
(value for key, value in attributes.items() if key.endswith(":id")), None
|
|
185
187
|
)
|
|
186
188
|
if "name" in attributes and identifier:
|
|
187
|
-
|
|
189
|
+
out.append((attributes["name"], identifier))
|
|
190
|
+
return out
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def sheet_index(package: OpcFile, name: str) -> int:
|
|
194
|
+
"""A sheet's zero-based position among the workbook's sheets."""
|
|
195
|
+
sheets = sheet_entries(package.read(_WORKBOOK).decode("utf-8"))
|
|
196
|
+
for index, (found, _identifier) in enumerate(sheets):
|
|
197
|
+
if found == name:
|
|
198
|
+
return index
|
|
199
|
+
known = ", ".join(pair[0] for pair in sheets)
|
|
200
|
+
raise PowerQueryError(f"this workbook has no sheet named {name!r}; it has: {known}")
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def sheet_part(package: OpcFile, sheet: str | int) -> tuple[str, str]:
|
|
204
|
+
"""The worksheet part for a sheet name or one-based position, and the
|
|
205
|
+
name of the sheet."""
|
|
206
|
+
workbook = package.read(_WORKBOOK).decode("utf-8")
|
|
207
|
+
rels = package.read(_WORKBOOK_RELS).decode("utf-8")
|
|
208
|
+
targets = _relationship_targets(rels)
|
|
209
|
+
sheets = sheet_entries(workbook)
|
|
188
210
|
if not sheets:
|
|
189
211
|
raise PowerQueryError("this workbook lists no worksheets")
|
|
190
212
|
if isinstance(sheet, int):
|
|
@@ -432,13 +454,22 @@ def _widen_dimension(sheet: str, reference: str) -> str:
|
|
|
432
454
|
|
|
433
455
|
|
|
434
456
|
def _add_defined_name(package: OpcFile, sheet_name: str, number: int, reference: str) -> None:
|
|
457
|
+
"""The hidden name Excel gives an external data range.
|
|
458
|
+
|
|
459
|
+
``localSheetId`` is the zero-based position of the sheet the name
|
|
460
|
+
belongs to among the workbook's sheets, so it has to be looked up
|
|
461
|
+
rather than assumed. Writing a constant 0 was right only while the
|
|
462
|
+
table landed on the first sheet, and named a different sheet than the
|
|
463
|
+
reference did for any other, which Excel will not open.
|
|
464
|
+
"""
|
|
465
|
+
local = sheet_index(package, sheet_name)
|
|
435
466
|
raw = package.read(_WORKBOOK).decode("utf-8")
|
|
436
467
|
first, last = reference.split(":")
|
|
437
468
|
absolute = f"${column_letter(CellRef.parse(first).column)}${CellRef.parse(first).row}"
|
|
438
469
|
absolute += f":${column_letter(CellRef.parse(last).column)}${CellRef.parse(last).row}"
|
|
439
470
|
quoted = f"'{sheet_name}'" if re.search(r"[^A-Za-z0-9_]", sheet_name) else sheet_name
|
|
440
471
|
defined = (
|
|
441
|
-
f'<definedName name="ExternalData_{number}" localSheetId="
|
|
472
|
+
f'<definedName name="ExternalData_{number}" localSheetId="{local}" hidden="1">'
|
|
442
473
|
f"{quoted}!{absolute}</definedName>"
|
|
443
474
|
)
|
|
444
475
|
empty = re.search(r"<definedNames\s*/>", raw)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_database.accdb
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_database_module.accdb
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_document.docm
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_excel_addin.xlam
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_presentation.pptm
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsb
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsm
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsx
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/engine_skeleton.accdb
RENAMED
|
File without changes
|
{pyopenvba-5.2.1 → pyopenvba-5.2.2}/src/pyopenvba/_templates/blank_files/engine_skeleton.mdb
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|