pyOpenVBA 5.2.4__tar.gz → 6.1.0__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.4 → pyopenvba-6.1.0}/.gitignore +3 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/PKG-INFO +419 -3
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/README.md +418 -2
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/architecture.md +61 -7
- pyopenvba-6.1.0/docs/excel_checklist.csv +1935 -0
- pyopenvba-6.1.0/docs/host_completeness.md +182 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/ms-ovba-implementation-guide_v2.md +9 -8
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/roadmap.md +75 -5
- pyopenvba-6.1.0/docs/vba_runtime.md +1451 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/pyproject.toml +4 -1
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/__init__.py +3 -1
- pyopenvba-6.1.0/src/pyopenvba/_a1.py +220 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_host.py +399 -147
- pyopenvba-6.1.0/src/pyopenvba/_new_project.py +194 -0
- pyopenvba-6.1.0/src/pyopenvba/_package_signature.py +104 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_ppt_container.py +19 -4
- pyopenvba-6.1.0/src/pyopenvba/_references.py +209 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/__init__.py +513 -529
- pyopenvba-6.1.0/src/pyopenvba/_templates/blank_files/blank_presentation.pptm +0 -0
- pyopenvba-6.1.0/src/pyopenvba/_xml.py +75 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_facade.py +3 -3
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_format.py +5 -1
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_sql.py +4 -1
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_vba.py +0 -121
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/database.py +12 -43
- pyopenvba-6.1.0/src/pyopenvba/apps/__init__.py +6 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/__init__.py +555 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_arrays.py +235 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_autofill.py +702 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_autofilter.py +970 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_bridge.py +86 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_calc.py +593 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_clipboard.py +592 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_control_refs.py +108 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_controls.py +386 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_copy_names.py +84 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_dimensions.py +1656 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_duplicates.py +153 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_dynamic_file.py +208 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_editing.py +361 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_engine_book.py +307 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_evaluate.py +85 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_events.py +127 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_find.py +222 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_font_rows.py +683 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_formats.py +1082 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_formula_format.py +112 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_io.py +1891 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_merges.py +98 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_model.py +3985 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_named_api.py +71 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_names.py +74 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_notes.py +650 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_notes_file.py +299 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_number_format.py +147 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_protection.py +654 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_radios.py +238 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_refresh.py +265 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_region.py +84 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_row_formats.py +498 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_shape_api.py +166 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_shapes.py +799 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_shared.py +101 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_sheet_copy.py +114 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_sheet_move.py +87 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_sort.py +426 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_special_cells.py +197 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_spills.py +188 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_styles.py +862 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_table_edits.py +355 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_tables.py +1074 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_typing.py +525 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_validation.py +670 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_visible.py +118 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_windows.py +997 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/excel/_worksheet_functions.py +202 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/powerpoint/__init__.py +220 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/powerpoint/_bridge.py +94 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/powerpoint/_io.py +118 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/powerpoint/_model.py +790 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/word/__init__.py +179 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/word/_bridge.py +103 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/word/_io.py +80 -0
- pyopenvba-6.1.0/src/pyopenvba/apps/word/_model.py +646 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/excel.py +31 -3
- pyopenvba-6.1.0/src/pyopenvba/exceptions.py +104 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/__init__.py +49 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_arity.py +71 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/__init__.py +32 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/catalog.py +72 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/cells.py +45 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/collate.py +200 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/dates.py +214 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/evaluator.py +828 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/__init__.py +47 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/aggregate.py +370 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/arithmetic.py +756 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/arrays.py +451 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/common.py +277 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/conditional.py +140 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/database.py +270 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/dates.py +442 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/distributions.py +1281 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/engineering.py +929 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/financial.py +1508 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/information.py +257 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/lambdas.py +194 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/logical.py +189 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/lookup.py +454 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/matrix.py +130 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/statistics.py +727 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/subtotal.py +243 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/functions/text.py +643 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/host.py +59 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/lexer.py +494 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/nodes.py +435 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/numbers.py +209 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/parser.py +245 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/precise.py +405 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/reference.py +390 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/registry.py +197 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/special.py +521 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_calc/values.py +423 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_deep.py +63 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_display.py +643 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_formula2.py +423 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_inventory.py +19 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_parse.py +879 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_prefixes.py +410 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_r1c1.py +144 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_spell.py +592 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_structured.py +290 -0
- pyopenvba-6.1.0/src/pyopenvba/formula/_values.py +395 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/__init__.py +89 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_ast.py +439 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_constants_data.py +5577 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_intrinsics.py +1310 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_inventory.py +56 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_inventory_data.py +660 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_lex.py +304 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_objects.py +346 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_parse.py +1274 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_preprocess.py +246 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_runtime.py +1963 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_scripting.py +152 -0
- pyopenvba-6.1.0/src/pyopenvba/interpreter/_values.py +1122 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/__init__.py +59 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_eval.py +530 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_inventory.py +26 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_inventory_data.py +193 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_library.py +2099 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_parse.py +627 -0
- pyopenvba-6.1.0/src/pyopenvba/mlang/_values.py +397 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerpoint.py +17 -4
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_sheets.py +3 -37
- pyopenvba-6.1.0/src/pyopenvba/shapes/__init__.py +34 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_docx.py +404 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_docx_text.py +126 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_drawingml.py +195 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_pptx.py +248 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_values.py +232 -0
- pyopenvba-6.1.0/src/pyopenvba/shapes/_xlsx.py +1000 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/vba.py +46 -5
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/word.py +15 -3
- pyopenvba-5.2.4/src/pyopenvba/_templates/blank_files/blank_presentation.pptm +0 -0
- pyopenvba-5.2.4/src/pyopenvba/exceptions.py +0 -35
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/LICENSE.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/power_query.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/research/access_complex/README.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/research/access_designs/README.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/research/access_macros/README.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/research/access_write/README.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/docs/research/pcode/README.md +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/__main__.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_deflate.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_oforms_pages.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_oforms_records.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_database.accdb +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_database_module.accdb +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_document.docm +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_excel_addin.xlam +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsb +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsm +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsx +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/engine_skeleton.accdb +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/blank_files/engine_skeleton.mdb +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/form.blob +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/form.lvprop +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/form.propdata +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/form.prototypes +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/form.typeinfo +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/report.blob +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/report.lvprop +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/report.propdata +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/report.prototypes +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/_templates/designs/report.typeinfo +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/__init__.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_alloc.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_btree.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_collation.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_collation_general_legacy.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_compact.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_complex.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_datapage.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_ddl.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_designs.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_index.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_lval.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_macros.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_pages.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_props.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_queries.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_rows.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_schema.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_storage.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_tdef.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access/_validate.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/access_read.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/cfb.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/forms.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/__init__.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_binary.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_files.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_mashup.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_metadata.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_opc.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_package.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_refresh.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/_section.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/powerquery/workbook.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/src/pyopenvba/vba_pcode.py +0 -0
- {pyopenvba-5.2.4 → pyopenvba-6.1.0}/tests/fuzz_corpus/README.md +0 -0
|
@@ -36,6 +36,9 @@ Thumbs.db
|
|
|
36
36
|
tests/fixtures/*.xlsm
|
|
37
37
|
tests/fixtures/*.xls
|
|
38
38
|
|
|
39
|
+
# Workbooks the measuring scripts build to ask live Office a question
|
|
40
|
+
tests/fixtures/mlang/_scratch/
|
|
41
|
+
|
|
39
42
|
# Manually-generated Excel verification set (rebuilt by
|
|
40
43
|
# scripts/build_excel_verification_set.py)
|
|
41
44
|
tests/live_excel_testing/_excel_verify/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pyOpenVBA
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.1.0
|
|
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
|
|
@@ -140,6 +140,29 @@ pip install -e ".[dev]"
|
|
|
140
140
|
The four host classes share the same module API: `module_names()`,
|
|
141
141
|
`get_module()`, `set_module()`, `save()`.
|
|
142
142
|
|
|
143
|
+
They also share `references()`, `add_reference()` and `remove_reference()`.
|
|
144
|
+
These edit the VBA project's library references, as in Tools > References:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
with ExcelFile("workbook.xlsm") as wb:
|
|
148
|
+
wb.add_reference("Word") # Excel, Word, PowerPoint and Access presets
|
|
149
|
+
wb.add_reference("Scripting", "420B2830-E718-11CF-893D-00A0C9054228",
|
|
150
|
+
path="C:/Windows/System32/scrrun.dll")
|
|
151
|
+
for reference in wb.references():
|
|
152
|
+
print(reference.name, reference.guid, reference.version)
|
|
153
|
+
wb.remove_reference("Word") # also accepts a GUID; returns whether removed
|
|
154
|
+
wb.save()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Adding an existing GUID or removing an absent reference is a no-op.
|
|
158
|
+
The existing Access `drop_reference()` spelling remains available and raises
|
|
159
|
+
if the reference is absent. VBA and the file's own host library are implicit;
|
|
160
|
+
they are not listed or added. MSForms cannot be removed while UserForms exist.
|
|
161
|
+
Removing a library does not rewrite code that names its types. Library paths
|
|
162
|
+
are resolution hints; adding a reference does not install the library or add
|
|
163
|
+
its implementation to the headless runtime. Use these methods to persist edits,
|
|
164
|
+
rather than mutating `VBAProject.references` directly.
|
|
165
|
+
|
|
143
166
|
### Excel
|
|
144
167
|
|
|
145
168
|
```python
|
|
@@ -504,6 +527,341 @@ What the format is, and how each rule was measured, is in
|
|
|
504
527
|
|
|
505
528
|
---
|
|
506
529
|
|
|
530
|
+
## Running the macros
|
|
531
|
+
|
|
532
|
+
Reading and writing VBA is one thing; this runs it. `ExcelApplication`
|
|
533
|
+
is an Excel instance in memory, with a VBA interpreter attached: load a
|
|
534
|
+
workbook, execute a macro, look at what it did, write the file back.
|
|
535
|
+
|
|
536
|
+
```python
|
|
537
|
+
from pyopenvba.apps.excel import ExcelApplication
|
|
538
|
+
|
|
539
|
+
app = ExcelApplication.open("report.xlsm") # sheets, names, queries, macros
|
|
540
|
+
app.run("BuildReport")
|
|
541
|
+
print(app.describe()) # a readable dump of the grid
|
|
542
|
+
app.save("report_out.xlsm")
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
State can also be made up from nothing, with no file at all:
|
|
546
|
+
|
|
547
|
+
```python
|
|
548
|
+
app = ExcelApplication()
|
|
549
|
+
app.add_workbook()
|
|
550
|
+
app.add_module('Sub Main()\n Range("A1").Value = 42\nEnd Sub\n', name="Module1")
|
|
551
|
+
app.run("Main")
|
|
552
|
+
app.sheet(1).value("A1") # 42
|
|
553
|
+
app.evaluate('Range("A1").Value * 2') # 84
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
Failures are three separate exceptions, because they mean different
|
|
557
|
+
things: `VBACompileError` for VBA that does not compile,
|
|
558
|
+
`VBARuntimeError` for an error VBA itself would raise, carrying the
|
|
559
|
+
number `Err` would hold, and `VBAUnsupportedError` for real VBA that
|
|
560
|
+
pyOpenVBA does not implement. The third is never trappable by
|
|
561
|
+
`On Error`: a gap here must not be swallowed and reported as a result.
|
|
562
|
+
|
|
563
|
+
Formulas are calculated, not just carried: write one from a macro and
|
|
564
|
+
read the answer back.
|
|
565
|
+
|
|
566
|
+
```python
|
|
567
|
+
app.add_module('''
|
|
568
|
+
Sub Total()
|
|
569
|
+
Range("A1:A3").Value = 10
|
|
570
|
+
Range("B1").Formula = "=SUM(A1:A3)"
|
|
571
|
+
End Sub
|
|
572
|
+
''', name="Module1")
|
|
573
|
+
app.run("Total")
|
|
574
|
+
app.sheet(1).value("B1") # 30.0
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
About a hundred worksheet functions are implemented; anything else
|
|
578
|
+
Excel has says so by name rather than quietly answering `#NAME?`.
|
|
579
|
+
|
|
580
|
+
Power Query is evaluated too. Refreshing a query works out its M and
|
|
581
|
+
writes the rows to the sheet it loads to, so the table, its queryTable
|
|
582
|
+
and the saved file all follow:
|
|
583
|
+
|
|
584
|
+
```python
|
|
585
|
+
app = ExcelApplication.open("sales.xlsx")
|
|
586
|
+
app.refresh_query("Summary") # the rows, headers first
|
|
587
|
+
app.save("sales_out.xlsx")
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Queries can name each other, `Excel.CurrentWorkbook()` reads the
|
|
591
|
+
workbook's own tables and named ranges, and a source this cannot reach
|
|
592
|
+
without a network or a driver reports itself rather than guessing.
|
|
593
|
+
|
|
594
|
+
Word and PowerPoint run their macros too, each with its own object
|
|
595
|
+
model:
|
|
596
|
+
|
|
597
|
+
```python
|
|
598
|
+
from pyopenvba.apps.word import WordApplication
|
|
599
|
+
from pyopenvba.apps.powerpoint import PowerPointApplication
|
|
600
|
+
|
|
601
|
+
doc = WordApplication.open("report.docm")
|
|
602
|
+
doc.run("Relabel")
|
|
603
|
+
doc.save("report_out.docm")
|
|
604
|
+
|
|
605
|
+
deck = PowerPointApplication.open("deck.pptm")
|
|
606
|
+
deck.run("Rebuild")
|
|
607
|
+
deck.slide(1).shapes() # what is on the first slide
|
|
608
|
+
deck.save("deck_out.pptm")
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
Shapes are read and written on all three surfaces: adding, moving,
|
|
612
|
+
resizing, renaming, retyping and deleting, with the macro a click runs
|
|
613
|
+
attached or removed. In Excel that is `Shape.OnAction`, form-control
|
|
614
|
+
buttons included; in PowerPoint it is
|
|
615
|
+
`ActionSettings(ppMouseClick).Run`; Word has no macro on a shape and
|
|
616
|
+
says so rather than pretending.
|
|
617
|
+
|
|
618
|
+
```python
|
|
619
|
+
app.add_module('''
|
|
620
|
+
Sub Draw()
|
|
621
|
+
Dim sh As Object
|
|
622
|
+
Set sh = ActiveSheet.Shapes.AddFormControl(0, 100, 50, 90, 30)
|
|
623
|
+
sh.Name = "Go"
|
|
624
|
+
sh.OnAction = "Refresh"
|
|
625
|
+
sh.TextFrame.Characters.Text = "Refresh"
|
|
626
|
+
End Sub
|
|
627
|
+
''', name="Module1")
|
|
628
|
+
app.run("Draw")
|
|
629
|
+
app.save("with_button.xlsm") # Excel opens it as a button
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
The same worksheet shapes can be edited directly from Python:
|
|
633
|
+
|
|
634
|
+
```python
|
|
635
|
+
app = ExcelApplication.open("report.xlsm", with_vba=False)
|
|
636
|
+
sheet = app.sheet(1)
|
|
637
|
+
sheet.add_button(name="Refresh", left=100, top=50, width=90, height=30,
|
|
638
|
+
text="Refresh", macro="RefreshReport")
|
|
639
|
+
sheet.update_shape("Refresh", left=120, text="Refresh report")
|
|
640
|
+
print(sheet.shape("Refresh").control) # control details
|
|
641
|
+
sheet.update_shape("Refresh", macro="") # unlink its macro
|
|
642
|
+
sheet.remove_shape("Refresh")
|
|
643
|
+
app.save("report_out.xlsm")
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
`Range.Formula` and `Range.FormulaR1C1` support scalar and array writes, with
|
|
647
|
+
shared bounds, error and merge handling. `FormulaR1C1` converts relative,
|
|
648
|
+
absolute and mixed references. Both properties return scalar or
|
|
649
|
+
two-dimensional array results, including requested trailing blank cells.
|
|
650
|
+
References survive save/reopen as ordinary A1 formulas. Array writes support
|
|
651
|
+
custom lower bounds, single-axis expansion, mixed values and formulas, and
|
|
652
|
+
Excel's `#N/A` filling for uncovered cells.
|
|
653
|
+
|
|
654
|
+
VBA `Range.Find`, `FindNext` and `FindPrevious` support single-area searches
|
|
655
|
+
over formula text or displayed values, with whole/partial matching,
|
|
656
|
+
wildcards, case sensitivity, traversal order and wraparound. Whole-sheet
|
|
657
|
+
searches keep empty cells sparse. Multi-area, comment and format searches,
|
|
658
|
+
and `MatchByte=True`, remain unsupported.
|
|
659
|
+
|
|
660
|
+
One `ExcelApplication` can hold multiple workbooks. Workbook handles let Python
|
|
661
|
+
callers select and save a particular book without depending on the active book:
|
|
662
|
+
|
|
663
|
+
```python
|
|
664
|
+
source_book = app.add_workbook()
|
|
665
|
+
source = app.sheet(1, workbook=source_book)
|
|
666
|
+
source.set_value("A1", 10)
|
|
667
|
+
destination_book = app.open_workbook("destination.xlsx")
|
|
668
|
+
destination = app.sheet(1, workbook=destination_book)
|
|
669
|
+
source.copy_range("A1:B5", destination, "D2", name_conflict="rename")
|
|
670
|
+
copied_sheet = source.copy(after=destination) # omit before/after for a new book
|
|
671
|
+
copied_sheet.move(before=destination)
|
|
672
|
+
app.save("destination.xlsx", workbook=destination_book)
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
VBA supports `Workbooks.Add`, `Open`, `Activate`, `Close`, and `Worksheet.Copy`
|
|
676
|
+
before/after a sheet in another open workbook. Copies preserve modeled cells,
|
|
677
|
+
merges and relevant names. Range copies import names used by formulas, including
|
|
678
|
+
aliases. `name_conflict="reuse"` (the default) uses the destination definition,
|
|
679
|
+
matching unattended Excel; `"rename"` imports names with unused `_2`, `_3`, etc.
|
|
680
|
+
suffixes and rewrites copied formulas; `"error"` rejects collisions before making
|
|
681
|
+
changes. Names referencing the source sheet retain their cell addresses on the
|
|
682
|
+
destination sheet; they do not shift with the paste offset. External-link range
|
|
683
|
+
copies, relative name imports, sheet-copy name conflicts, drawings,
|
|
684
|
+
controls and advanced worksheet metadata are explicitly unsupported. Opening
|
|
685
|
+
additional workbooks does not create independent VBA execution projects.
|
|
686
|
+
|
|
687
|
+
VBA `Worksheet.Move Before:=...` / `After:=...` uses the same anchors as Copy.
|
|
688
|
+
Omitting both moves the sheet into a new workbook. Cross-book moves invalidate
|
|
689
|
+
held VBA worksheet, range and local-name objects (error 424), matching Excel;
|
|
690
|
+
reacquire them from the destination. Python `move` returns the new sheet view.
|
|
691
|
+
Same-book reordering preserves object identity. Moving the last sheet to an existing
|
|
692
|
+
workbook closes the empty source; moving its only sheet to a new workbook raises
|
|
693
|
+
1004. Moves that need external links or unsupported sheet-content transfer fail
|
|
694
|
+
before changing either workbook.
|
|
695
|
+
|
|
696
|
+
Named ranges support create/read/update/delete through VBA `Names` collections
|
|
697
|
+
and shared Python APIs. `app` operates on workbook names; `app.sheet(...)`
|
|
698
|
+
operates on worksheet-local names. Snapshots include scope, reference, visibility
|
|
699
|
+
and comments; renaming updates dependent formulas.
|
|
700
|
+
|
|
701
|
+
```python
|
|
702
|
+
app.add_named_range("Revenue", "=Sheet1!$B$2:$B$10", comment="Sales totals")
|
|
703
|
+
app.sheet(1).add_named_range("Revenue", "=$C$2:$C$10", visible=False)
|
|
704
|
+
print(app.named_ranges()) # workbook and local definitions
|
|
705
|
+
print(app.named_range("Revenue")) # workbook definition
|
|
706
|
+
app.update_named_range("Revenue", new_name="Sales", refers_to="=Sheet1!$B$2:$B$20")
|
|
707
|
+
app.sheet(1).update_named_range("Revenue", comment="Local override")
|
|
708
|
+
app.remove_named_range("Sales")
|
|
709
|
+
app.sheet(1).remove_named_range("Revenue")
|
|
710
|
+
app.save("named_ranges.xlsm")
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
Whole-row/column `Insert` and `Delete` update cell references, including absolute
|
|
714
|
+
and cross-sheet references, range boundaries and defined names, and move row
|
|
715
|
+
heights and column widths. Deleted targets become `#REF!`. Partial-cell reference
|
|
716
|
+
updates and full formatting/metadata movement remain incomplete; sheets with
|
|
717
|
+
merges or shapes are explicitly unsupported.
|
|
718
|
+
|
|
719
|
+
`Range.Copy Destination:=...` handles overlapping copies, blank source cells,
|
|
720
|
+
repeated destination blocks and relative formula shifts, and copies each
|
|
721
|
+
cell's format. Merged-cell and multi-area copies, large destinations and
|
|
722
|
+
clipboard pastes remain incomplete.
|
|
723
|
+
|
|
724
|
+
`Range.Merge`, `UnMerge`, `MergeCells` and single-cell `MergeArea` support
|
|
725
|
+
merged-region editing and save/reopen. Ordinary overlapping merges expand
|
|
726
|
+
to include the existing regions; `Across=True` merges each row separately.
|
|
727
|
+
Excel's first nonempty value or formula is retained, and partial clears raise
|
|
728
|
+
error 1004. Multi-area merges, across merges over existing multi-row regions,
|
|
729
|
+
and full merge-formatting parity remain outside the measured support.
|
|
730
|
+
|
|
731
|
+
Cell formats read and write the way Excel does: `Font`, `Interior`,
|
|
732
|
+
`Borders`, `BorderAround`, the alignment and protection properties,
|
|
733
|
+
`NumberFormat` and `ClearFormats`. A read over several cells answers Null
|
|
734
|
+
when they differ, theme colours take their tints the way Excel computes
|
|
735
|
+
them, and a border between two cells is stored and read the way Excel
|
|
736
|
+
shares it. A workbook Excel formatted reads back exactly as Excel reads
|
|
737
|
+
it, and a save adds only the stylesheet entries the file lacks, spelled
|
|
738
|
+
as Excel spells them. Formatting whole rows, whole columns or the whole
|
|
739
|
+
sheet keeps the row, column and sheet formats Excel keeps, with the
|
|
740
|
+
cells Excel makes where they cross, and saves them as Excel does. Named
|
|
741
|
+
cell styles and conditional formats are not implemented yet.
|
|
742
|
+
|
|
743
|
+
Row heights, column widths and hidden rows and columns behave as they do
|
|
744
|
+
in Excel on a 96-DPI display, the one the model emulates: `RowHeight = 20`
|
|
745
|
+
reads back 20, draws 19.5pt tall and saves as Excel saves it; `Hidden`,
|
|
746
|
+
`UseStandardHeight`, `UseStandardWidth`, `Height`, `Width`, `Left`, `Top`
|
|
747
|
+
and a sheet's standard sizes follow, and all of it is read from and saved
|
|
748
|
+
to the file. A row grows or shrinks with the fonts its cells, its own
|
|
749
|
+
format and its columns show, as Excel's does, from heights measured in
|
|
750
|
+
live Excel for the common Office and Windows fonts; a row
|
|
751
|
+
whose height rests on an unmeasured font, a mix of fonts, or wrapped
|
|
752
|
+
text reports itself unsupported, and column `AutoFit` measures no text
|
|
753
|
+
yet.
|
|
754
|
+
|
|
755
|
+
`shapes()` and `shape(name)` return detached snapshots, including each
|
|
756
|
+
control's linked cell, list range and value. Use `update_shape` to make
|
|
757
|
+
an edit. `add_shape` creates a measured AutoShape and `add_textbox`
|
|
758
|
+
creates a horizontal text box; coordinates and sizes are nonnegative
|
|
759
|
+
points. `update_control(name, linked_cell="$H$1", list_range="$J$1:$J$3")`
|
|
760
|
+
edits saved form-control bindings (list ranges apply to dropdowns and
|
|
761
|
+
list boxes); use an empty string to disconnect a binding. References
|
|
762
|
+
may be A1 cells/ranges or workbook and worksheet-local names in this
|
|
763
|
+
workbook. These binding edits leave cell
|
|
764
|
+
values untouched. `set_control_value(name, 1)` checks a checkbox; use
|
|
765
|
+
`-4146` or `0` to uncheck it and `2` for mixed. Changed states write
|
|
766
|
+
True, False or #N/A to the linked cell. Direct cell writes and calculated
|
|
767
|
+
formulas also update linked checkboxes, including links across sheets.
|
|
768
|
+
VBA exposes the same state through `Shape.ControlFormat.Value`; its
|
|
769
|
+
`LinkedCell` setter follows Excel's rebinding behavior.
|
|
770
|
+
For single-selection dropdowns and list boxes backed by ranges,
|
|
771
|
+
`set_control_value(name, 2)` selects the second row; zero clears the
|
|
772
|
+
selection. These controls synchronize numeric indexes with linked cells.
|
|
773
|
+
VBA also supports `ControlFormat.ListFillRange` and `ListCount`.
|
|
774
|
+
Changing the source range clamps the selection or restores it from the
|
|
775
|
+
linked cell without overwriting that cell.
|
|
776
|
+
|
|
777
|
+
Named bindings support aliases, local-name precedence and changes to a
|
|
778
|
+
name's target. A linked name covering a rectangle writes its top-left
|
|
779
|
+
cell. Missing names remain saved; they provide no linked target and an
|
|
780
|
+
empty list source. Shrinking or deleting a named list source adjusts its
|
|
781
|
+
selection. Named `CHOOSE`, `IF`, `INDEX`, `OFFSET` and `INDIRECT` formulas support dynamic
|
|
782
|
+
targets, including cell-driven list sizes and addresses. `INDEX` supports
|
|
783
|
+
single-area sources and zero indices selecting whole rows or columns.
|
|
784
|
+
Invalid `INDEX` and `OFFSET` ranges provide empty sources.
|
|
785
|
+
`CHOOSE` and `IF` resolve only the selected branch; selected scalar values
|
|
786
|
+
or errors provide empty sources, and cell-driven conditions redirect bindings.
|
|
787
|
+
`INDIRECT` accepts A1 and absolute R1C1 addresses, including quoted sheet names.
|
|
788
|
+
Other reference formulas, multi-area `INDEX`, relative R1C1 `INDIRECT`,
|
|
789
|
+
cyclic aliases and external workbook bindings remain explicitly unsupported.
|
|
790
|
+
|
|
791
|
+
Inline lists support `control_items`, `add_control_item`,
|
|
792
|
+
`update_control_item`, `remove_control_item`, and `clear_control_items`.
|
|
793
|
+
Their VBA equivalents are `List(index)`, `AddItem`, `RemoveItem`, and
|
|
794
|
+
`RemoveAllItems`. Item edits adjust selection indexes without changing
|
|
795
|
+
the linked cell. Use `set_control_selection_mode(name, 2)` and
|
|
796
|
+
`set_control_selection(name, [1, 3])` for multi-selection; mode 3 is
|
|
797
|
+
extended selection. Snapshots expose `items`, `selection_mode`, and
|
|
798
|
+
`selected_indices`. VBA supports `ControlFormat.MultiSelect` and
|
|
799
|
+
`Shape.DrawingObject.Selected(index)`. A multi-selection list's scalar
|
|
800
|
+
`Value` read raises Excel error 1004.
|
|
801
|
+
|
|
802
|
+
`set_control_items(name, ["one", "two"])` replaces the entire list after
|
|
803
|
+
validating every string. VBA supports whole-list `ControlFormat.List`
|
|
804
|
+
reads and assignments: reads return a detached one-based Variant array,
|
|
805
|
+
or Null when empty. VBA assignments follow Excel's error behavior,
|
|
806
|
+
including retaining a successfully written prefix when a later array
|
|
807
|
+
element is invalid. Python replacement validates before making changes.
|
|
808
|
+
|
|
809
|
+
As in Excel, adding or replacing an item in a range-backed list
|
|
810
|
+
disconnects the source and starts a new inline list; it does not edit
|
|
811
|
+
the source cells. Clearing disconnects it too, while removing individual
|
|
812
|
+
range-backed items raises an error. These conversions reset selection
|
|
813
|
+
and can write zero to the linked cell. Edit the source cells directly
|
|
814
|
+
when the control should remain range-backed.
|
|
815
|
+
Spinners and scroll bars support `set_control_value` and VBA
|
|
816
|
+
`ControlFormat.Value`, `LinkedCell`, `Min`, `Max` and `SmallChange`.
|
|
817
|
+
Scroll bars also expose `LargeChange`; Excel rejects that member on
|
|
818
|
+
spinners. Direct values must fit the bounds. Numeric linked-cell values
|
|
819
|
+
clamp the control while preserving the cell, text preserves its state,
|
|
820
|
+
and empty/error cells reset it to its minimum. Snapshots retain numeric
|
|
821
|
+
bounds and increments, and saved controls preserve their type and state.
|
|
822
|
+
Excel can reconcile a saved control with its linked cell when opening
|
|
823
|
+
the file; its stored value alone does not determine the displayed state.
|
|
824
|
+
`add_form_control(control_type, name="Choices", left=12, top=20)` creates
|
|
825
|
+
buttons (0), checkboxes (1), dropdowns (2), group boxes (4), labels (5),
|
|
826
|
+
list boxes (6), option buttons (7), scroll bars (8), and spinners (9).
|
|
827
|
+
It uses the same geometry, caption, macro and name arguments as `add_button`.
|
|
828
|
+
Multi/extended lists retain selections when switching between those two
|
|
829
|
+
modes. Changing their source keeps only selected indexes that fit the new
|
|
830
|
+
range; switching to single selection clears them. VBA rebinding writes the
|
|
831
|
+
stored scalar index when the destination cell differs, even though a
|
|
832
|
+
multi-selection list does not expose a scalar `Value` getter.
|
|
833
|
+
Radio groups support off (`-4146` or `0`) and on (`1`) through
|
|
834
|
+
`set_control_value` and VBA `ControlFormat.Value`. Selecting a button clears
|
|
835
|
+
its peers and writes its one-based group index to the shared linked cell;
|
|
836
|
+
cell edits select that index without rewriting the cell. Text preserves
|
|
837
|
+
selection; empty/error cells and out-of-range indexes clear it. Group
|
|
838
|
+
membership stays stable during ordinary movement and is reconstructed from
|
|
839
|
+
group-box geometry on reopening, matching Excel. Non-overlapping boxes
|
|
840
|
+
support interleaved creation and regrouping, including a separate unboxed
|
|
841
|
+
group. Splitting preserves selected buttons; merging keeps the first
|
|
842
|
+
selected button in control order. Adding a box to split interleaved radios
|
|
843
|
+
preserves the linked cell's previous index. Radios can also be created
|
|
844
|
+
inside existing overlapping or nested boxes: earlier boxes win partial
|
|
845
|
+
overlaps, while a strictly nested inner box wins regardless of creation
|
|
846
|
+
order. Adding and deleting those boxes transfers group links and selections
|
|
847
|
+
with Excel's measured behavior. A late nested box leaves the link with its
|
|
848
|
+
surviving outer group. An identical box can transfer the original link to
|
|
849
|
+
an unlinked unboxed group; an already linked unboxed group keeps its link.
|
|
850
|
+
Deleting a radio leaves the linked cell
|
|
851
|
+
unchanged; deleting the leader retains the link for a boxed group and
|
|
852
|
+
clears it for an unboxed group.
|
|
853
|
+
Creating pictures, charts and shape groups remains tracked work.
|
|
854
|
+
Removing a control cleans up its worksheet record, properties
|
|
855
|
+
part, relationship and VML while preserving other controls and notes.
|
|
856
|
+
|
|
857
|
+
Every answer the interpreter, the calculation engine and the three
|
|
858
|
+
object models give was measured in the application itself rather than
|
|
859
|
+
assumed, and a file nobody changed saves back byte for byte. What is
|
|
860
|
+
implemented, what is not, and how it was measured is in
|
|
861
|
+
[docs/vba_runtime.md](https://github.com/WilliamSmithEdward/pyOpenVBA/blob/main/docs/vba_runtime.md).
|
|
862
|
+
|
|
863
|
+
---
|
|
864
|
+
|
|
507
865
|
## Supported formats
|
|
508
866
|
|
|
509
867
|
### Excel
|
|
@@ -535,6 +893,39 @@ outside the project, so it is read and written in every package above.
|
|
|
535
893
|
| `.potm` | Macro-enabled template | yes | yes | no |
|
|
536
894
|
| `.ppt` | Legacy (PowerPoint 97-2003) | yes | yes | no |
|
|
537
895
|
|
|
896
|
+
### Files with no VBA project
|
|
897
|
+
|
|
898
|
+
A file saved before its first macro has no VBA project: no
|
|
899
|
+
`vbaProject.bin` in a `.xlsm`, `.docm` or `.pptm`, and no project storage
|
|
900
|
+
in a binary file. That is its normal shape, and it opens like any other.
|
|
901
|
+
`has_vba_project()` says False, listing reads such as `module_names()`,
|
|
902
|
+
`vba_modules()`, `forms()` and `references()` answer empty, and a read or
|
|
903
|
+
write that needs the project raises `NoVBAProjectError`, a kind of
|
|
904
|
+
`VBAProjectError`:
|
|
905
|
+
|
|
906
|
+
```python
|
|
907
|
+
with ExcelFile("book.xlsm") as wb:
|
|
908
|
+
if wb.has_vba_project():
|
|
909
|
+
print(wb.module_names())
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
`add_vba_project()` gives a `.xlsm`, `.docm` or `.pptm` a project, the
|
|
913
|
+
one its application makes for a first macro. In Excel that is a
|
|
914
|
+
document module for the workbook and one for each sheet, named as Excel
|
|
915
|
+
names them; in Word it is `ThisDocument`; in PowerPoint it is empty. Add
|
|
916
|
+
modules to it and save:
|
|
917
|
+
|
|
918
|
+
```python
|
|
919
|
+
with ExcelFile("book.xlsm") as wb:
|
|
920
|
+
if not wb.has_vba_project():
|
|
921
|
+
wb.add_vba_project().add_module("Module1", "Public Sub Hello()\r\nEnd Sub\r\n")
|
|
922
|
+
wb.save()
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
A project its application would not write is not written here either:
|
|
926
|
+
Excel writes only the code names for one with no code in it, and
|
|
927
|
+
PowerPoint nothing for one with no module.
|
|
928
|
+
|
|
538
929
|
### Access
|
|
539
930
|
|
|
540
931
|
| Extension | What it is | Read | Write | create_new |
|
|
@@ -581,8 +972,19 @@ the file still asks for the original password in the VBE.
|
|
|
581
972
|
|
|
582
973
|
### Digitally signed projects
|
|
583
974
|
|
|
584
|
-
Any change to the macros invalidates a digital signature.
|
|
585
|
-
|
|
975
|
+
Any change to the macros invalidates a digital signature. Excel, Word and
|
|
976
|
+
PowerPoint keep the signature of a `.xlsm`, `.docm` or `.pptm` in parts
|
|
977
|
+
beside `vbaProject.bin`, and `vba_signature()` reads it from there:
|
|
978
|
+
|
|
979
|
+
```python
|
|
980
|
+
info = wb.vba_signature()
|
|
981
|
+
info.present, info.kinds, info.parts
|
|
982
|
+
# (True, ['v3', 'agile', 'legacy'], ['xl/vbaProjectSignatureV3.bin', ...])
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
On a save that changes the project, the library takes the signature out
|
|
986
|
+
as the applications do: the parts, their relationships and their entries
|
|
987
|
+
in `[Content_Types].xml`. It then emits a `UserWarning`:
|
|
586
988
|
|
|
587
989
|
```python
|
|
588
990
|
import warnings
|
|
@@ -591,6 +993,11 @@ warnings.filterwarnings("error", category=UserWarning) # treat as fatal
|
|
|
591
993
|
wb.save(allow_invalidate_signature=True) # or accept it
|
|
592
994
|
```
|
|
593
995
|
|
|
996
|
+
A save that changes nothing keeps the signature. A signature in a binary
|
|
997
|
+
`.xls`, `.doc` or `.ppt` file is not looked for: there it lives in the
|
|
998
|
+
file's property sets or a string table, and no signed binary file has
|
|
999
|
+
been measured.
|
|
1000
|
+
|
|
594
1001
|
---
|
|
595
1002
|
|
|
596
1003
|
## Out of scope
|
|
@@ -642,6 +1049,7 @@ For more:
|
|
|
642
1049
|
- [docs/power_query.md](https://github.com/WilliamSmithEdward/pyOpenVBA/blob/main/docs/power_query.md): how Excel stores Power Query, and how each rule was measured.
|
|
643
1050
|
- [docs/ms-ovba-implementation-guide_v2.md](https://github.com/WilliamSmithEdward/pyOpenVBA/blob/main/docs/ms-ovba-implementation-guide_v2.md): a language-agnostic guide to re-implementing MS-OVBA.
|
|
644
1051
|
- [docs/roadmap.md](https://github.com/WilliamSmithEdward/pyOpenVBA/blob/main/docs/roadmap.md): per-feature status.
|
|
1052
|
+
- [docs/host_completeness.md](docs/host_completeness.md): whole-host completion criteria and the Excel coverage audit; Excel, then Word, then PowerPoint.
|
|
645
1053
|
|
|
646
1054
|
---
|
|
647
1055
|
|
|
@@ -677,6 +1085,14 @@ PyPI when a `v*.*.*` tag is pushed.
|
|
|
677
1085
|
|
|
678
1086
|
---
|
|
679
1087
|
|
|
1088
|
+
## Built with this
|
|
1089
|
+
|
|
1090
|
+
[xlide-mcp](https://github.com/WilliamSmithEdward/xlide_mcp)
|
|
1091
|
+
is an MCP server built on this. It gives an AI agent the VBA, the
|
|
1092
|
+
UserForms and the Power Query inside an Office file, so a model can read
|
|
1093
|
+
a macro, rewrite it and save it back without anyone exporting modules by
|
|
1094
|
+
hand. Every container this library opens is one that server can reach.
|
|
1095
|
+
|
|
680
1096
|
## License
|
|
681
1097
|
|
|
682
1098
|
[MIT](https://github.com/WilliamSmithEdward/pyOpenVBA/blob/main/LICENSE.md).
|