pyOpenVBA 6.3.1__tar.gz → 6.3.3__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.
Files changed (234) hide show
  1. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/PKG-INFO +1 -1
  2. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/architecture.md +6 -5
  3. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/ms-ovba-implementation-guide_v2.md +10 -4
  4. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/pyproject.toml +1 -1
  5. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/__init__.py +1 -1
  6. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_host.py +2 -2
  7. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/__init__.py +168 -171
  8. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_database.accdb +0 -0
  9. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsm +0 -0
  10. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/forms.py +47 -23
  11. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/vba.py +9 -9
  12. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/.gitignore +0 -0
  13. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/LICENSE.md +0 -0
  14. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/README.md +0 -0
  15. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/excel_checklist.csv +0 -0
  16. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/host_completeness.md +0 -0
  17. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/power_query.md +0 -0
  18. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/research/access_complex/README.md +0 -0
  19. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/research/access_designs/README.md +0 -0
  20. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/research/access_macros/README.md +0 -0
  21. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/research/access_write/README.md +0 -0
  22. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/research/pcode/README.md +0 -0
  23. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/roadmap.md +0 -0
  24. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/docs/vba_runtime.md +0 -0
  25. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/__main__.py +0 -0
  26. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_a1.py +0 -0
  27. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_deflate.py +0 -0
  28. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_new_project.py +0 -0
  29. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_oforms_pages.py +0 -0
  30. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_oforms_records.py +0 -0
  31. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_package_signature.py +0 -0
  32. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_ppt_container.py +0 -0
  33. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_references.py +0 -0
  34. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_relationships.py +0 -0
  35. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_database_module.accdb +0 -0
  36. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_document.docm +0 -0
  37. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_excel_addin.xlam +0 -0
  38. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_presentation.pptm +0 -0
  39. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsb +0 -0
  40. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/blank_workbook.xlsx +0 -0
  41. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/engine_skeleton.accdb +0 -0
  42. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/blank_files/engine_skeleton.mdb +0 -0
  43. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/form.blob +0 -0
  44. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/form.lvprop +0 -0
  45. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/form.prototypes +0 -0
  46. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/form.typeinfo +0 -0
  47. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/report.blob +0 -0
  48. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/report.lvprop +0 -0
  49. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/report.prototypes +0 -0
  50. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_templates/designs/report.typeinfo +0 -0
  51. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/_xml.py +0 -0
  52. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/__init__.py +0 -0
  53. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_alloc.py +0 -0
  54. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_btree.py +0 -0
  55. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_collation.py +0 -0
  56. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_collation_general_legacy.py +0 -0
  57. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_compact.py +0 -0
  58. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_complex.py +0 -0
  59. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_datapage.py +0 -0
  60. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_ddl.py +0 -0
  61. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_designs.py +0 -0
  62. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_facade.py +0 -0
  63. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_format.py +0 -0
  64. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_index.py +0 -0
  65. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_lval.py +0 -0
  66. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_macros.py +0 -0
  67. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_pages.py +0 -0
  68. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_props.py +0 -0
  69. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_queries.py +0 -0
  70. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_rows.py +0 -0
  71. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_schema.py +0 -0
  72. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_sql.py +0 -0
  73. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_storage.py +0 -0
  74. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_tdef.py +0 -0
  75. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_themes.py +0 -0
  76. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_validate.py +0 -0
  77. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/_vba.py +0 -0
  78. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access/database.py +0 -0
  79. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/access_read.py +0 -0
  80. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/__init__.py +0 -0
  81. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/__init__.py +0 -0
  82. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_arrays.py +0 -0
  83. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_autofill.py +0 -0
  84. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_autofilter.py +0 -0
  85. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_bridge.py +0 -0
  86. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_calc.py +0 -0
  87. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_cell_styles.py +0 -0
  88. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_clipboard.py +0 -0
  89. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_control_refs.py +0 -0
  90. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_controls.py +0 -0
  91. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_copy_names.py +0 -0
  92. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_dimensions.py +0 -0
  93. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_duplicates.py +0 -0
  94. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_dynamic_file.py +0 -0
  95. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_editing.py +0 -0
  96. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_engine_book.py +0 -0
  97. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_evaluate.py +0 -0
  98. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_events.py +0 -0
  99. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_find.py +0 -0
  100. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_font_rows.py +0 -0
  101. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_formats.py +0 -0
  102. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_formula_format.py +0 -0
  103. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_hyperlinks.py +0 -0
  104. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_hyperlinks_file.py +0 -0
  105. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_io.py +0 -0
  106. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_merges.py +0 -0
  107. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_model.py +0 -0
  108. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_named_api.py +0 -0
  109. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_names.py +0 -0
  110. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_notes.py +0 -0
  111. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_notes_file.py +0 -0
  112. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_number_format.py +0 -0
  113. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_protection.py +0 -0
  114. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_radios.py +0 -0
  115. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_refresh.py +0 -0
  116. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_region.py +0 -0
  117. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_row_formats.py +0 -0
  118. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_shape_api.py +0 -0
  119. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_shapes.py +0 -0
  120. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_shared.py +0 -0
  121. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_sheet_copy.py +0 -0
  122. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_sheet_move.py +0 -0
  123. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_sort.py +0 -0
  124. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_special_cells.py +0 -0
  125. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_spills.py +0 -0
  126. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_styles.py +0 -0
  127. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_table_edits.py +0 -0
  128. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_tables.py +0 -0
  129. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_text_columns.py +0 -0
  130. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_typing.py +0 -0
  131. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_validation.py +0 -0
  132. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_visible.py +0 -0
  133. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_windows.py +0 -0
  134. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/excel/_worksheet_functions.py +0 -0
  135. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/powerpoint/__init__.py +0 -0
  136. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/powerpoint/_bridge.py +0 -0
  137. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/powerpoint/_io.py +0 -0
  138. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/powerpoint/_model.py +0 -0
  139. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/word/__init__.py +0 -0
  140. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/word/_bridge.py +0 -0
  141. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/word/_io.py +0 -0
  142. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/apps/word/_model.py +0 -0
  143. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/cfb.py +0 -0
  144. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/excel.py +0 -0
  145. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/exceptions.py +0 -0
  146. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/__init__.py +0 -0
  147. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_arity.py +0 -0
  148. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/__init__.py +0 -0
  149. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/catalog.py +0 -0
  150. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/cells.py +0 -0
  151. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/collate.py +0 -0
  152. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/dates.py +0 -0
  153. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/evaluator.py +0 -0
  154. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/__init__.py +0 -0
  155. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/aggregate.py +0 -0
  156. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/arithmetic.py +0 -0
  157. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/arrays.py +0 -0
  158. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/common.py +0 -0
  159. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/conditional.py +0 -0
  160. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/database.py +0 -0
  161. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/dates.py +0 -0
  162. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/distributions.py +0 -0
  163. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/engineering.py +0 -0
  164. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/financial.py +0 -0
  165. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/information.py +0 -0
  166. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/lambdas.py +0 -0
  167. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/logical.py +0 -0
  168. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/lookup.py +0 -0
  169. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/matrix.py +0 -0
  170. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/statistics.py +0 -0
  171. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/subtotal.py +0 -0
  172. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/functions/text.py +0 -0
  173. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/host.py +0 -0
  174. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/lexer.py +0 -0
  175. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/nodes.py +0 -0
  176. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/numbers.py +0 -0
  177. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/parser.py +0 -0
  178. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/precise.py +0 -0
  179. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/reference.py +0 -0
  180. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/registry.py +0 -0
  181. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/special.py +0 -0
  182. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_calc/values.py +0 -0
  183. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_deep.py +0 -0
  184. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_display.py +0 -0
  185. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_formula2.py +0 -0
  186. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_inventory.py +0 -0
  187. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_parse.py +0 -0
  188. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_prefixes.py +0 -0
  189. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_r1c1.py +0 -0
  190. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_spell.py +0 -0
  191. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_structured.py +0 -0
  192. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/formula/_values.py +0 -0
  193. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/__init__.py +0 -0
  194. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_ast.py +0 -0
  195. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_constants_data.py +0 -0
  196. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_intrinsics.py +0 -0
  197. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_inventory.py +0 -0
  198. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_inventory_data.py +0 -0
  199. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_lex.py +0 -0
  200. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_objects.py +0 -0
  201. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_parse.py +0 -0
  202. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_preprocess.py +0 -0
  203. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_runtime.py +0 -0
  204. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_scripting.py +0 -0
  205. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/interpreter/_values.py +0 -0
  206. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/__init__.py +0 -0
  207. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_eval.py +0 -0
  208. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_inventory.py +0 -0
  209. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_inventory_data.py +0 -0
  210. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_library.py +0 -0
  211. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_parse.py +0 -0
  212. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/mlang/_values.py +0 -0
  213. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerpoint.py +0 -0
  214. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/__init__.py +0 -0
  215. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_binary.py +0 -0
  216. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_files.py +0 -0
  217. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_mashup.py +0 -0
  218. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_metadata.py +0 -0
  219. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_opc.py +0 -0
  220. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_package.py +0 -0
  221. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_refresh.py +0 -0
  222. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_section.py +0 -0
  223. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/_sheets.py +0 -0
  224. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/powerquery/workbook.py +0 -0
  225. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/__init__.py +0 -0
  226. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_docx.py +0 -0
  227. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_docx_text.py +0 -0
  228. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_drawingml.py +0 -0
  229. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_pptx.py +0 -0
  230. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_values.py +0 -0
  231. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/shapes/_xlsx.py +0 -0
  232. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/vba_pcode.py +0 -0
  233. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/src/pyopenvba/word.py +0 -0
  234. {pyopenvba-6.3.1 → pyopenvba-6.3.3}/tests/fuzz_corpus/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyOpenVBA
3
- Version: 6.3.1
3
+ Version: 6.3.3
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
@@ -85,11 +85,12 @@ Other files:
85
85
  {pull,push,ls,forms,access-ls,access-pull,access-push,access-disasm,disasm}`.
86
86
  `disasm` / `access-disasm` accept `--with-source` to interleave
87
87
  the original VBA source with the decoded p-code.
88
- - `_templates/__init__.py`: generated module embedding a
89
- zlib-compressed base85 blob of a freshly Excel-authored empty `.xlsm`,
90
- consumed by `ExcelFile.create_new()`. Regenerated from
91
- `tests/live_excel_testing/freshly_touched.xlsm` by
92
- `scripts/bake_empty_template.py`. No binary fixtures ship in the wheel.
88
+ - `_templates/__init__.py`: generated module embedding, as
89
+ zlib-compressed base85 blobs, the empty files each host's
90
+ `create_new()` starts from. The `.xlsm` section is baked by
91
+ `scripts/bake_excel_template.py` from
92
+ `_templates/blank_files/blank_workbook.xlsm`, with Module1 written as
93
+ source alone, and the other bake scripts splice in theirs.
93
94
 
94
95
  ### 1.1 Layer rules
95
96
 
@@ -399,7 +399,7 @@ that you need the `PROJECT` stream (Section 8).
399
399
  Each module's source lives at `/VBA/<MODULESTREAMNAME>`. Layout:
400
400
 
401
401
  ```
402
- [ PerformanceCache prefix ] MODULEOFFSET bytes (opaque; preserve)
402
+ [ PerformanceCache prefix ] MODULEOFFSET bytes (preserve only for unedited modules)
403
403
  [ CompressedSourceCode ] bytes from MODULEOFFSET to EOF
404
404
  ```
405
405
 
@@ -415,13 +415,19 @@ text = decode(raw, code_page=project.code_page)
415
415
  **Write (in-place source replacement):**
416
416
 
417
417
  ```pseudo
418
- old = cfb.get_stream_in_storage("VBA", module.stream_name)
419
- prefix = old[:module.text_offset] # preserve verbatim
420
418
  new_raw = encode(new_text, code_page=project.code_page)
421
419
  new_body = ovba_compress(new_raw)
422
- cfb.write_stream_in_storage("VBA", module.stream_name, prefix + new_body)
420
+ cfb.write_stream_in_storage("VBA", module.stream_name, new_body)
421
+ module.text_offset = 0
422
+ module.prefix_bytes = b""
423
+ # Rewrite the dir stream with this module's MODULEOFFSET = 0.
423
424
  ```
424
425
 
426
+ An edited module is source-only: retaining its old compiled prefix would
427
+ leave removed comments and string literals readable in the saved file.
428
+ Unedited modules keep their streams, including their cached p-code.
429
+ The project cache is invalidated as before so Office compiles the source.
430
+
425
431
  **Write (new module):**
426
432
 
427
433
  ```pseudo
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pyOpenVBA"
7
- version = "6.3.1"
7
+ version = "6.3.3"
8
8
  description = "Read and write VBA macros and Excel Power Query in pure Python, no dependencies."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -293,4 +293,4 @@ def push_power_query(
293
293
  """
294
294
  return _push_queries(src_dir, workbook, out=out, encoding=encoding, remove_missing=remove_missing)
295
295
 
296
- __version__ = "6.3.1"
296
+ __version__ = "6.3.3"
@@ -19,10 +19,10 @@ import zipfile
19
19
  from pathlib import Path
20
20
  from typing import ClassVar, TypeVar
21
21
 
22
- from pyopenvba.cfb import CFB
23
22
  from pyopenvba._new_project import with_project
24
23
  from pyopenvba._package_signature import signature_parts, without_signature
25
24
  from pyopenvba._references import ReferenceManager, module_offset, reference_spans
25
+ from pyopenvba.cfb import CFB
26
26
  from pyopenvba.exceptions import NoVBAProjectError, UnsupportedFormatError, VBAProjectError
27
27
  from pyopenvba.forms import VBAForm, create_form, form_names, read_form, read_forms
28
28
  from pyopenvba.vba import (
@@ -677,7 +677,7 @@ class VBAHostFile(ReferenceManager):
677
677
  write_back_modules(cfb, project)
678
678
 
679
679
  # 5. Rewrite the dir + PROJECT streams when the module set's
680
- # identity has changed (add / rename / delete). PROJECT is
680
+ # identity or a module's source offset has changed. PROJECT is
681
681
  # always rewritten on a structural save so that any duplicate
682
682
  # declarations or stale ``[Workspace]`` entries left behind by
683
683
  # earlier buggy writes are scrubbed via the dedup pass in
@@ -15,178 +15,175 @@ import base64
15
15
  import zlib
16
16
 
17
17
  # --- XLSM template (generated by bake_excel_template.py) ---
18
- # Source bytes: 8703 | zlib: 8090 | base85: 10113
18
+ # Source bytes: 8547 | zlib: 7936 | base85: 9920
19
19
  _EMPTY_XLSM_B85 = (
20
- "c-nn=1yCGY*X;md(BQ#6_~7m?!9BRU4({&m5;Q@AOCY$r26uN0?hcRp-FkKZoBw-ny5{uho>"
21
- "{xA_BmU6Ed^<)cNhQw0QT)m0w_ykQ`Ch300iCv0O)Ubv_!zRPA0ZadMfUACXPDvZZ_8CiJfv"
22
- "#Bq$-"
23
- "L6m8uhr5Z(qQA{fy;~vw5R}ck^$A<nSziMpPR*&k^&8ID|AYn|~PKhA5O6fx^1B3a#i)a0gF"
24
- "JaVh;HSg8zO&QPD~f<l2o!|Fs}=jKmbjI7-"
25
- "p&3|O$RX?Zzf_}+GxHG+n>!uMh6jr1~rH+`TL;0+7D4jcHAsHX-P&&IzAEEK8^-"
26
- "I=QztnxB{JoM){Ja)tT!OaiP&pEfo1d>x8LzD^1!KvDUQivT<}x#a(6f&JGy!(~onH4Ndykm"
27
- "JQcw@=e%nj8~L;2shrhc(lDdWu^+-"
28
- "NTlpTPMy5U8YAJKA3O(qOpj=RBXqg@uyy0CoxI<sP`$XhtZ}&)5SI>+lZfa|U3X%RxDC-"
29
- "p8i^YqFav$Ihz3aL#Fxu`V;S|4U^VI>?!Ol9Ks;nE#AkgNvZnp;)cSmldb8q8pHvn0nuF@_a"
30
- "@jE74h}s*ug7V7-G)~9*K*XVGJZUIo5?@|00?hqJqHtOM+W-"
31
- "8#`4KdDJUis;Ck~qPf(+)nU;`f`mtEhs^}~XcH)8UJQ;dI(NaAYaxOyc)%x?^S8&L}$?p0L&"
32
- ")z1Pr8);4Rg8F9WMD|@i@h^UiAqFDi|DM~He~b3gXQC|?2<%v@zjX)z*w<vb*m-"
33
- "`TGMU8@9{nMNH4@(3Utxi5a?;)z&_cfRl}DRh?QLB<MNP}dX8@oMw`-"
34
- "2J9c&<L_ICgG1on?+l>x2)@sz!o7x0e3Vb{Mr9jXwwKUBqYBt9+ze2H$VX=cT8zwt)>E!WGy"
35
- "O-IOJzV1t0`fI7Pv)kvL<xmz@drx*kwp9a5dU@xFMo-IArt^m{&tD{cE`<{!4>RaWe5ga{bz"
36
- "rsXo0t=F#Oik7GM3`3V~6TB|H%}W#y~{(Tmp2kF2@uk_tBH29pgX4{H()jWs;U?7u6B>^Sk;"
37
- "9HIA~hUaV771M<d_ye~QMTj3YIZE_Q&&J$?4Pk+x2l1MwR2;7as3(W>NARAO4dF?x55Q>dMg"
38
- "*ufTcJFL_dEHh$F5+mnyA?&N0#!)u3%&mZ&p0QR9(`dc{UF_RF_f(Sr4w5D>w%WL3LPZE<^6"
39
- "-=7XUzsBH52hti>e{NZn9yDUcJ47L*Idd$x&rJolH;oybT3R8!5@$A=z5M#&yc@TMUo#wE>y"
40
- "c|#Ik8nOrGsTPhLJUV5<;_`B?LG28BnFx>qIMI>c5&{DwBN@Toh6o?b-"
41
- ">3m2E4LFuYZj3Nx;N6$I#7WPyvDUw6MaiA2Rl}ziYy3GO4dpfie)qQEEIuYjD3zv%o4##&Hy"
42
- "IvcyHsANA@5rsiYO3B{=3am3*$nbMPm{N2zTHLEl-"
43
- "`(F^Q=#gO7o85nUw<&e6*g^z|)AtnAUM3&i#F)kz{x&*-&6B*{@Tv!5-"
44
- "@9q}d<bksjb#qR4lteDOO*v~5smT21|~cpRx#3`L=FRbS(I`D>_Vgkwv)E7_S0F*Yv<=@Mhl"
45
- "Eg<HU$)b;9l2h3%RYM<!laR{8b=4PIr^>^fIz8VO<~?Ufl<i`yoa5J@*9Uax$bvP@k|s!9=o"
46
- "K@)*T$i*q33?V647g?jCOWMFOl4y8LHT?5T#~#QCMYIG+)tVu1d`c#SfWeQa(bCF~M{D1{4m"
47
- "oZ4pu<w64b%H~<d23lS`UcMgG<G<n$aTbvN6yDEH+uU&D)V&JOZN?al9xH$4E07gBpp5F)1;"
48
- "6e-"
49
- "#$#lkW)iNN2+^yzbT7+w&(7doP87433t=9)zxktr`b<iFNGgiMiSw*^xK#AK}ExNIw{obyAI"
50
- "qgalMy1coI+BbVg;q<`wAe2#9lsK;<I+FsAh-Yv!}&AK99E<XN!H7e+#BUiY)_5rNYZoLyeG"
51
- ";<st(OX}7KNH@hcmLF{<6LraM8jZKcsN#3Y34h2ujh%r8VdJp)+ybEc65nz@f<*csfro_!YB"
52
- "SJRtBp+3KtUt4X(f5+WRe=R)0FMdF<-"
53
- "!y4CQ&<JR;z1p%~(b=|5`Ug6BDggV}&{C7C|U%`X!-)4nxISTjhaQr(>{m-"
54
- "EMJ7pyZ$#pZLh~0i#?o8*iS3(gklH-"
55
- "6a<_YS8&^Al>vY0(!B<0{K8u<wn93iHb_lot}+Doez=xP`mPX`SxmJ-"
56
- ";ZUsRW)diI%bjn{8IU!<G>T7{9cyQHN}vn_XOP-"
57
- "%Vih8B1V3EEfsP4wM(DrYWJG1lO$B4^)uGs+O;X;arE);MtKi4)85jdua#P*X^IuAaE0s{hq"
58
- "mc}hJ{-"
59
- "k6^^gf%cOQ#=$gce1KCe?9JJCr{kvT`&20u}CbsHxaUl{b)`@em7+=ookrI#a+4j$(Tl3vw("
60
- "36Tl|;wB%BKYLdT~S@pe%U2}d$U=Y_rya5b-"
61
- "c<psjO9rksy)S&yV#&*5sFzkQwm!r9fiIXG4e@;w)`7CQn54=Q-"
62
- "0yw*sd_>w`eO{Bypvsp@6+i4Quw1#3J6jNE%7o6hXFYCKqmbq<W>8&?34F9?|IvWw)UP|vEf"
63
- "ykzS=cfDsU*pQ^XZ{6+}59qL57^0d0-"
64
- "<9=_KW=03DLCYlYaA^>~&&zUJwpdjjV|E+%~e;mEh<^fJuVUgM0OYfP~Z5l*Sw7TmHm3P8E8"
65
- "WuKmJO`p-"
66
- "`$Zm0?1xPS?Ha_6Ym8@p5(Ft@}7`Q(2C**r>%zSnpB7%aK8NN3%8i=q7#SbaNNO+&}p4}{vZ"
67
- "geT=sX41AAq9ViKPCV5`swA;Y>*c9f^^~VOPLI9ThTdSt>{V0%Ax9lqpSffL-"
68
- ")tI>%zURD*lVH-faD?22=FO<t7Eq+)oQuPy{ax$Gvf_yBn37#XVL^B!EwYqPXi+_+#iEQ=(9"
69
- "{wu)39j)7^_?hp7ug)^;<&SxwZhPtu&oGW$v0l(;57wH;2N+J-"
70
- "_fqHsN=}M6Fg|S9(?Y!#?3_)A2rREq3XbbL#-"
71
- "Pz^u264&>HzW&f8G4(tV5~uhiAZ2O+!EE6dZ@FyGt{r_Zz!I>MOY!~$WJA|O3+2X+t~Tfh`#"
72
- "V*Keo2C?STHh@HhH3LT5k#0G0Ib=IU+Xoy<*aO#UAKv*yQ|W3gLxAKI|?Uy1imYRR--"
73
- "nABz0zb+h&9wC{wXl>uoPN2C`DG?vw;B`Xw?oLblLt0Eo`>#5{MgYzI-ZfsuY7j@VKYxT*tf"
74
- "pObGNnwjQFiJJMLjt6e7YmNzoR|afGJH<R|`Y<Wv<_hjK3tzYK&T7uP^Xb7LRWU4bA*rkRry"
75
- "s71<GTjPHG9s2v%45~)=(8chuG4|M9Ed8W!ia8g3N`Z&3zNwnDVLJ=@g{Uc%BYz6jG>DgOO>"
76
- "D2m`S{O<g^JAC@_@q`T88xvSeU$IMhe^e|1_kMD7sU4|%<oT*yoT3equS~~z#Uo1e01Rx0a<"
77
- "9h3&KYwoR4|<nbD7&@gaNwY8e+?@*<@x8Ai|7yLH||%8gz*=K^|!7u@Ezog5ZO=7aWQ6s?(7"
78
- ">TmMtKX50n1JcmHuY1&~|Gs5)qxE?6n3Xd(dj_wfU3a_3c`V=87NYiTb8@X486P|kws3={q3"
79
- "7|uyD=WWroh$pM+-RE;cuEczUC%x3ZTVyHx9bxAt>ab-_TO|S=R*5pBy@?3D1D@m6=A>PRP)"
80
- "5&^ZJXCAWjnI04QoN=#heMhi!QLP4J=`;a?k%BAIZ9xsvvtmRQI2*XpSkx)7a-"
81
- ";DVOk(uBz?shY{&HeJBl%ulU=klNstou5{-"
82
- "DywyzC}WCi~IC(%=flZ;Cb<3Z|&vj*{q#oON`+4hN0d4@p#R5pk><ld1JU<&-"
83
- ";Fb$oDapfuE%V27lN24zci)y8J|~^Qh9d0*LX<wHPL8fED5=b$H;qC<X4>0d5!^hiDUmo}J7"
84
- "`^t0|AY1u=uu2eKUKlua|sBC8OkSM&uOERKT{w(t7k-"
85
- "$q60#_tE6I{<4^z}hzX@v+`3JJJL<80J#XojNkH5aGz<ifzkerzirzFrcu0J{8Zrn(TnX!^8"
86
- "`M%F~a4Gh>aSx7TD^ENJTgZDU0X+(J-0ytKnA#-"
87
- "@xZXdD%H3=I{NYZpXB{6#9KqMP7TPVVye_t4*6&eYNOs1Jv`JgxCyNqrhsoCO~Z8W{~ILZ!n"
88
- "0xr|kymynoig2d#W1c^0GmCd{8%<IL9Pp5VSpxhC5pNNqwvX$s9q}o5p%Z+6ZWqw`e`zC{Gl"
89
- "m#2_UcfkYewQ^uZY=To=v%d6Mk1gB0S*n5)U`VY>N5JDa7g%B-7@O_@FtmgaKz<+|-"
90
- "AnPFq9n>2K&FICkJcd0ysU(1EPs<5A3zHkfH-MB^>qB~6!Xm<`ta8D>Tr>{{)S;#XI8QO8(0"
91
- "$5vRsVuWS&av@<iUd|QO&GTpqe3ypx3-"
92
- "O1up;SG~ILmBG0+>=v3)daNd&;(Ze7V?FNd`>glMT7&e*Uyp<h`mj<9K^Ln$uFPwS(XFj6BP"
93
- "3q&~?an)o=m+g5YmPHTg7yz>~a+xD%I!TiMtdZaGIVitT&1v=<_<VTPh2-Ze-"
94
- "B2~Hmh}}7Xfu4&Sp|WB+lz^((T-O*F$yH<($#M^(O^kfUj4@w<OM?0RKwTXN-T!zV#-"
95
- "{YaDlNOZs3mgG_Qbj?9?*E~`c$H4NE5j#=jw@9!(6FZRfI6mSdXfRCxbP?9JXJ#DjSr(kX5v"
96
- "gr*gGSq%=_`7OZb6<fFU{#)_atg%naGEDUH5Kgp7Kh-107@C-"
97
- "S)UUJ2>kQKFQJRr3kX7q<Wc3HD8dt8dMyx`4?vOV?gX=?n62RoxR>s(Qsu>?nga0Crup=FRR"
98
- "=1+H_0!>!nPcSq&B|uSYtUbUKmhV?w2@jL6PHKyq33TCq9fAs)?YSm+H3N+f2c9{i&n-"
99
- "tYYtkxEAzxW%Pzqy;N3Fex+O6tKhu?{z>1a7tZ||W%*R45U?u)Ar&`hK5*3PtEZ_2gN+~(c@"
100
- "%$p_rjp33cr1&zh?3{H5i$_GLSF(~<=_y%a3tjDxR%I3k(_!S|p5|F8<8EDt=2U8bm3SFdAK"
101
- "uz>QusWCD<sacNL!_SC*bBi`9WIrUX5-"
102
- "<B(z6|2&TETP6I@%YIVB6p3yFvgP#XYD>)&uk4=}feG~;ccEl_nmL`qRQTk<(2!!R6KtPZv?"
103
- "YNN{r6wX&lRRp{CKhO+$#rC@>H(w6i@AU))S_fZbmLVuY?+DGW(J_!VAYe^q~zITbwxpg1~u"
104
- "+ATKUQ|&5{!!3py^OBYAw^aYFZ(qK&I3$-"
105
- "EUyp6F}=b2ebxngeCqVN~cU=<zN`Mrn=#k~0`1(fR%*@b{W04C%^~zB@{F&ERxpcmZjtE3x+"
106
- "J84n6(4CEs^c(bn6pTjb$&$e*lrY}ppatW7JT-"
107
- "WUAJ^tE(3{0i<p_Kp1h8u6zgKi!Rt}CvM**XWXd$wreKsID`I;*CCbbW>brIZ;awQas^Xv-"
108
- "Js-vv_shH5h9t&LQBE0XX3E|88+?$#!bf0f4X$!k_ij41tUFpoq*s{|Sq$K*nvEz)t}wQy<z"
109
- "TWRVt!+wXxCrvNRzw#SX+6(uyFQ)E0xjro4dVM09%SzDiFGm;0LXkIwZK#l;yK3@V%N{a^_r"
110
- "H{xlffN9XxKy2or)z2yYw6+;>h$Ir!Llk;8?A94AQRMh-eJAXgo=>j#B;A9A0I$tvRf5+(km"
111
- "Jh}O@gBxBBrvRm>%6lQqiz9gQkNOx&So`3e34eejDduwGwt0k%1fmB!qNib>y$?Zuy>8UrPm"
112
- "|NYK)+bMs7iWR1cs}P~W*(x>mf(=l5*@^XL5bDsdJ~<Gq0xqJ;1!q9XMQSZQn!eOA~Mdw<2$"
113
- "=6mP&$=DS}CU0yEE~As9uHo6kI{zRsb29v4J4A#+Z$RdC(s4`W*H4i_InO>!$j3m2n%PND&4"
114
- "V{Mn4Bh$_)g-"
115
- "fy{sfnfnOHFN&cDwvr=@T5%%~abC^tAXT#MIvNM^BptLdt~&e;@m#vZ(S#zDFtvEb;^nLPf("
116
- "~5A@GqO^kq5ykM$gXf3=EV?jcBd_)P!-tS(BYU`ekohP{8>Pu8!+UWHWh4x>};i-"
117
- "{#{cza*edX}xPx}HY8n?fWd*>iL3?g)mBix}>WZ<Lf*M68pc!ueWNoc~Wy-_4OSu;t-"
118
- "4oK&)20c$vt9MMibXirY4pJYM&g1wF;2w_|C~+dQx$Oz?tX1k;i9z_T((#X^xSF8JZuPQCRk"
119
- "~r0RQECuO)m91XpC->wLLrEz_)C@-)EpFCy?8di-"
120
- "=ef`3Z9#n^);)mLcTx`t0VK<DIg7E*r8{)DmHzv}=tkds#|L!;(pR>13apypVQt6b%-"
121
- "OVkGP}b7a6s6(%xs&Kz&7_cM4*rRV|+z_Gr39AEqQ2DUUnEkFEgO7qs`{k?%*3=I?<z?LRPP"
122
- "V|Nrw#S;j*64EtugeSeQJwn2=|Zr_8wz!kU)p$h<g^(hPrc-"
123
- "X(RsQlp5RUP?u2=dGR^eNvBj7TCNCsj1$9(a(`zOzr_4*`oF+?-"
124
- "+cDlQWkKl=V+C?fny>1VvPQ4hUpEd`vH}w!!xKq+c4M7ynq5y@Pxrjn9(~sCA6KJe*?k}SJd"
125
- "b^Q(eVA=*Mkn%iw2DV)@7@1ewd(Bm+wkB8d?AqT(|s=nuYamd2Y)<FY*3l=w0iMQucMCIv%K"
126
- "350W1lNMK5+Ul49Y$?zgX*dn$sn1agSHtrpPxW~q)DZQ_j1fGX0X*P1R<|eDwv~^A;6XFRgb"
127
- "1oP@(=&QLhf{g4FUI}tynv!J3cv{4RD?n1><S`aZ_-"
128
- "j)ETbo6#}bM{_Hv2L*Ky;;U<(hRP8KSYjhK)fJPk61hxHgyN#+aWgdGjUCW3g^x{ew!HbfGs"
129
- "G?{u~DFE@#zEh#D_<hLz2NRWoS)F3L&-"
130
- "6L&QG*4a!84Bpfb5!!NAm?~(`U;CVcGKU*K1}L&*kFJ3!r9=bntA2N(JsB)9ESwT$#ir5L33"
131
- "imp65&RgXW*um)KbTY2=8_r_C~`>kR=da4k^OxM_*Hu@Kx`9LQ8uAu7$r~u*s>`)?JjH?c02"
132
- "oBkTnqaVzO~bR6slhv|=-zbMxeAip!(M9-&CsFfh{8=NLK>{ymf}HLDT$iRw3-"
133
- "6<QMVQPIq6&_!}-(!ci}KWagX~rWI{tnsS$G%tuH!3?*g#soAi#xEG)?Tm(R!$hBz-BWCj<c"
134
- "e}_b=sC-"
135
- "x{&UcLEV^UIKNu4>*gzVP`o^mPoTGUgGVX%5i+8lo>z86M{s1TnqyeW&eao5PCKhWeqyvydZ"
136
- "L_e9+`rU4a&_SfJZj|1guJeqJaEEzcIW^?)QtBc+6Z+wybSGV-"
137
- "v3)T@qEoNxG4)pM%JcfAq=bVe=M;3NR?s%L%aJm~$Y$4`ph~w=?2L{)3a#B*i110S#JglvdF"
138
- "i#;TurLXcK)SB&;xoC%FNX^X?)1#OTn0KQTmJAZg<H6kE80;?Y`>N9<%DyT9j)^!Rd5KL2Rb"
139
- "UL(I=3`r#`M<5afi-ka0fBi|UN$9oI}ua4QpcD3*Fw5ewbM{Bu`U|y+HP;J@Cncm_K&FdnXR"
140
- "lK@QRZ4fO)ZA<}=KRbOI#kjeNkdWIw87JRfRL120dVVCo0Q)vDw3kXjkNcD-"
141
- "}jtu#Wd;nh!l;ToLG2K5+Mye8`A?DNeqHo-"
142
- ">zjNqHeR<xyno!vy_V!SA!Q%ll3ZcjNY@33qt)p@LK9O`6`;~bG-"
143
- "P()gxD@5@72u_&a~Ot>Xq->&M^!I;rUnj!|S{R-(6DQ|!N{r~yMisAD-"
144
- "|!nP0BvHcV)m^m=l=&wr}>6iiD=nwnM&HyP?CRqsS3JLY=lfOaXm=6dM_~RwIUAWKR=$EY_q"
145
- "Us>rg(J%~>jVt<*&1s`!75S)wdN-"
146
- "}NsSpEeR846YgOn{ztEOcyYy*hG*u36^`MU)?TPy(R&ZUNqIOlr4($N<i=2yzDW2f9jW@MJ6"
147
- "h|X!Z0J~k9_;h|mv&OHIby3KTAbGksUa$nyxWAUM%2)X2^Si*^s&D~A|qw09*>Sn+@9e=rY7"
148
- "!TVvUz>Mm0}JJOP6xxs5PPYNkqrr72>#y0t>WJ#k-"
149
- "1VtDIB4vEAbGH+@K7k@)4XQSxDCd{$|yLWjJ#@GfIV}_|f_D_T1vg7Nnx`onDvZm1hO|Ehav"
150
- "xlnM787<=AIeCym|sNAN<BFFdpI`P3sWzl*Ii%dTz}OAz{p{U45Q05uV?o0$!P@@hdfZtt+|"
151
- "&66!8lbZC^4~RQY;u_13bF4pkmwesgr>d4JOg<M6F{j(hF9nHoB+;}|=|Zp$?(aHQd8XRbR<"
152
- "xiw+rdtB^ADpZCwOk}Cr;<&Tp+*U<Crmcri8gOiVP^*zjV-|-`WSkcc?8L-"
153
- "n&CEG>mkN|XOH{}ahLL|Q#3gk{6cGVVIVoY^U+XjC-ejkGKINjE4fCT#I6XopeDcag+4e^Dj"
154
- "csq1Kzw&!^cpaC9AUXN<?bwnJXh^wdJCvhQ0^jY*-w+?u&#1x-"
155
- "jvdP?^&$+MSR1#891#iG+E%}EMC|XHg}Ax8u`79o!sI+AlGb)Ylb1H^(9UZ<(;rOghhkEQFL"
156
- "GK#5VyHL@}fI?A0&Yo{F0v4d+2axuQXzV)agt&XrtyT3T$?+A(fIa&x|P+yZl}z7eB)1n273"
157
- "4<B<geM@$d%bu7ij?&x)7E;tC+Rh2L-"
158
- "<`SpR_cWTp?WBLg?suhm43~EV4nDeNk!q$c}Z5{5gx_G-1W-"
159
- "Ymn+a!0>1|^S7bXiTe9Ka+`8Cb!JoYdV)ZAY9BeMrD}Ud}*2j{l1gw2@vgc*EnhZ_(+|4U*H"
160
- "D2l0fu4>CY;M?ceLh|6=<X-"
161
- "!?s2w@V}d3S%PcMR!Ar*^WyDLNmR@ui(&K;a3F}E(8fj4s3oA?Kdtc0ga6vFUQ2z4yHje7#_"
162
- "~LVj%g3gt9qbv0J2;){cG783J7G4m=F8@X?>^S=no+>o#a<qA8wDR=bcYwkHXxd*_L~#9vj8"
163
- "s^bRC7X2%N#F_`;AdBqG9=y%$TJxCT2O53h)RT8F=!fEpN89-PrS3lDv-uzus!RcEiU_w8=e"
164
- "dV+0o3+1Kb0xJfDt))*78xU635M`Ajl@@@nmE?r40<15{TKoh+%ZO=$N%HUq=Fpw7BE9dnT_"
165
- "({CI%_MlI6q`(3+7C}>~-"
166
- "v?FT$@gZDj%O(yJuiTeEm!{2&kvtzCQI^rHlf^DSmM9gdc?4=+Zpyk9>A>?2(&18x9rxPn*!"
167
- "BEQzp?oIX5-"
168
- "s~&nS5UBk{enVcz!jj6Its<l4B`mt2a(`B=MvCsihD_DjZYMS=0^os;Le#w_RIc=^Ue;X!x0"
169
- "b?bqyH?^$EKU%4^syH1`nOI~9PWRVQ{&0BwiZVGp1LL_u)Et-E)hW|&|cx-Osf`oZf%c31!s"
170
- "0oAjYFu^lX0z1k)FIU;RukL=lctyM@PgsADo*il49B-"
171
- "tj73ANYkuliltu3;1WH16dnEch=M<)zh{)Ze6ehHjdP1)h4>T>x;r@^N1NlMC9IGrrlgQU3j"
172
- "^0rrQlgtKFXN|?o2`2gH=hAIFuee#2Fk>#M4m(i(!smS(HhCfiG*XrTYO8O;p0MVh*VdAk6>"
173
- "a%iJPtb~;7BZLnf)Eqa&)3%4Ds)fSP{~k^)<`cXRR<rOrJ4%`UDm*?c(>8%Sf0zNxQQcodZz"
174
- "`k^_*XZg*4}Q1AmG-%|i(m;=VF-&J;x`13as*G755a7-"
175
- "w3j@!gR&9lnRMtRf>I0md?F$}j^(#X1kkc#M`3zwlHXXmVnlZ?4FEOA`P+degcXfQXs;2YzK"
176
- "32)ms+6CRq+~WK`EfOE(3{Y#tW@oE8s$jV@$zDooVt|CH(#FrX^Ok(sd@+A-"
177
- "CHUe+qLObRY)LBIp0>RZUL*h8%LbBgD86rAMt!4}QU0fw4eadxLn$Y8+Ac97hMYn@AcdSnXI"
178
- "4;!2!3WF19{B<07x$Vq?oEw(7+I#{c(F0Xw&1|obB<^_k~y>PNiOF>nA1}7h<q_r9-"
179
- "^X5A`NHnx5|SlZ%XjFj=bTen9ZPe@}VaUG5FsM=}>djk!C);G(oGaj9xH){xKGBu>$ljBFtm"
180
- "!3ShjC7Hnli>W}!;ZolA_;IEnw4q^64h-"
181
- "df+2OA?nz;mb`{(l##5ps!*sVW92!PMS3qe62%mla*bO%iokH-"
182
- "l++Q|A_N0YS+e(Ohv+H@7Y(X>fkAEx=f7+832p;^pa6hIGuVRrD%K~W=pG=c?Y3fE9@p{vW("
183
- "QR5g9g(v!SUCFQk5)*!MhDe_>yUcm;;VxhE<YfxgB!E$4WBA5TEx~BMf-Smev54rWL5|pW1!"
184
- ">Z4m-"
185
- "()(_4A_W9_8Ek&rTa@gqx_YAsa2D^|{>B6he(6Je8i9)80fR_nqzKvYbNhH&1%lF|VB74Z3S"
186
- "(7nSb(t50Rr_YcDlL<-UnkQjjfx7z-"
187
- "HKYkE^|E|6NY2Z(N_#XqY5dTt({{;T2q5cERhx}iP>Yw006`y~=EWrPt{`04uKZTHg>=?uRz"
188
- "h#j>t^CQV|6@f5?!R*Ee;W9cb@<1C56T}L#GlYV-}nB33ZVa&x4-"
189
- "}8fIpJrKX48F|B@pAg#Q`s|G?V`{&(yvNJ9hv`W61|@P2!sHPK&x{y*0Iq!R"
20
+ "c-"
21
+ "nn=1yoyE*LHv+0g4xg;O_1&#kIwXy9N*LP~2tk;%+T2!L1Z8R=jv|clel@^{@G+@B979%DE@"
22
+ "^=Gj?m@3Zw$Re*bi0{{S!UOwc2%5-iu0~i26^c4Vr{c=Z7671k=?%-;u>FH?hqR--CZ&#Jnt"
23
+ "qezw5q3-i?G3BYDJ6|&U-p{t`c8TQQ_OZ~5=j27-"
24
+ "eGm+pfSVhyUhhGq6PFA1iMke5@r(|DqJL!{VSoIO~+Y;ndtJyQO~e65<W3l3`o=<{a!0+qu{"
25
+ "ichf+%)HG*g+a#O){z7ao=+gwo}6@>vaggd2Z*hs5Z%7uq8n@B;9O^#VuQfYv<IlwL6<_EA?"
26
+ "Ke0unyme*fvRp=dtXmI5W!NrpI>A<#sa?7wy|;1#TUTvcL%X{R(dw9T?!LLz2;ZjpGF_z=AI"
27
+ "f$?Ylw2?dridDFIZ`zx`{@?^VPLmNJD2d;{BcXke|f?6T&ES{w`AE1Xs7vr)f+d0e(9|fd$m"
28
+ "XJ@jM{iv?sW_CUY{YqW)|83s4lZv!+$&MdQ3<sZjpgodQk2y>fTvITROy^xUo=Bpjkn}?3aO"
29
+ "U$cfH<skO@aH^C=cn`L`A+c1BkU#u=<_DL>c7m<@Q#i0;AN)>3jm<JTn(Mg?Oa${{#>i3y5-"
30
+ "^6F%Z_;)&xUZAeMUKQW=NRAuCd|i1<l+4)avliKUB8c<A{k4Hs*VJGtPng`@4Y8Nr>OR5seY"
31
+ "%yh9bl~KWAX-`gWh~=7*sqIp;j+?M;M|U>&-"
32
+ "*U>6v}MvFGlJu!d$ny_Wtl8C#flR8oY0=g_*I!>Hes;SBM=6Z7FSH3mSL9jH4dx7+M9Sk-"
33
+ "I@MWXx(yj3<LGG!^d9sA#Jue*V}2)EByRGf~P9H6<C45xJ|FX@Rpw2<s_g)I&(yNZ`_{Uky;"
34
+ "^T;_dc%PE8;G#GR;0z2bwFMI0!xL@Qx$F(?YOD+2Rxr3i_X%bLIe097wv(O>R(*s(&u&bB6C"
35
+ "u<c*xGgS|~L5CBts`cYJz@r2qx~5z((!R2aizMcUUE4iZK98KLJ+|>wbNSt>Y;#M!U<%K#YL"
36
+ "FuzG1LWq=V4^NVNESVd`~2J6IGJzUYEDr(Bfp=Gt>kLf$>hJzBP@&ClT(!`Sc#Vqi0Wg)Zhm"
37
+ "&ox74m(3-"
38
+ "8*7$^Fba?s~kJog#Y=ANfSd*E0+Iz==q6KSC>XWceifdA2eRukP2SjHckhllcRM13w(`ReM8"
39
+ "i5X+%)MKsszOl;wFAc|RHuOyHa<?Yj_sbRU7fOK0;#wtXBL+lHt6x!LsQ?8q1;B1AB!q%IZv"
40
+ "{%AANx$%k6m%r1D&e2?CH)vm0H=MHk|0~B&uzK+tLrO<4RAGDo?tQ<Jf|pIb+r+WBn3wiLG!"
41
+ "9vRE}4!G?Nx;g@%ryB~^lk#yO$SLhfsQDrddy%<-4-"
42
+ "z>7hnu})fG(aV?Qa4J&Cei8nIBZgBI%EPFAT4`Fig=(0mWytkPS)TP$^{D=;#!;M7hkA)@3I"
43
+ "3-kPJ&-al?7a!Bwn9yvZ-"
44
+ "q1Ed1E>vf+d1pHeM9ltlh9hh+(!T3QIb318D2pgbrp}640JJdQh28^f?KtHE?UXWv$g6L-"
45
+ "Q2HtK4S5?FO{LEOfsYSdrh)F-fsZ+wSRc&<giE~AGH`w@DG2O9yg`tHcR?bO-ZKVu4xrj>fG"
46
+ "xGVuuQl5OQeIbqiV!jxe1Kk-"
47
+ "%9trGkL0doT6)eDJWd{ijH^X_n&r|58>xns2>Y)7t1mGvJ4(<n<#CLH#{I$Sr`)fu8-"
48
+ "CbGH0dKOfn9}TVJ&t;QuE*nX}vbAsKy)|>>%r(T$@&%XzpIYF=_-"
49
+ "pG^pbgS!^LKATnH9oc?bmrAE|S;(ZD^h^)^$4NguXiDbTu;f%%yOW}9omm{_<L;Ym>jx1#SP"
50
+ "!}HbpTze-=}L+>CRE*Y<C0-"
51
+ "PpU;BBli|_J3%;;C^wU1ZbXYgxxSMXSW#w#_5mjVgkS&!R{<;_w^U_x?*<O7E*6g&~iugKn7"
52
+ "!lduRB<~K(Q0`6FsScVes;jXYFV;BUR`79KYnZIjlJ>__-"
53
+ "NU!(1UewPH^@ZM2`CoGm?>*ELXY`NqY<!8w(F^y4=|LrIg-uJoNJr;s)7hz7zCly`P3bu#SU"
54
+ "l)M+g9W!JzR{-"
55
+ "pi4I|g1LGv2=JN?u|V;ot7~cbNL$PWgApN)%V_Wy6rZe!JA2A?&1%AyKN#i&Q2U(gX9sGVzZ"
56
+ "eIYXxM&fZc{Zy7@)rL_v4@t!;SnY4l-CLa@+;o+rIgS(7M8}r_sycb>-"
57
+ "3Ro+YtRjKeWTWUUZ-?qa^QVW^*T$}x5RPFPch!G^ip-|-"
58
+ "=Cah{j8CfbcHMqPn=pFYH?~T*44r!u#PNO-TEN-Y75^~TL{?rm_-v;!tsSglCL$EZ6&#-"
59
+ ">^AR<Fs;<9qE&fZlVEp+_KlN#uWE{3H2;JOiEU&q+m$si75^jBVQ>A@0u9My-YSzx3@JB{6!"
60
+ "I>zj%fqrvr<9kh3l*E&!ax}Kvyf-a8OpyEmOE8p-"
61
+ "20MadtPD~{y*`{#md~=)rIx13;Uls%bqp_FOp#ZPOjzd(RNoJSLHJ43gy#e_IrzMmamjg7G&"
62
+ "77;0v9&4%@V76a>mx->t+3-"
63
+ "#hWtHWRrH8cYaChe_g=bWOZ1PqyZJxNC`U2;^r~q!!>9S`SA%O3f8zMl*v{OJCScWIGY-"
64
+ "9^ZQ=@-5`!vJ{h!ern68#9iq(%j~<vm3|ZHnzm^zpj5Alpxm?M*Y~OQJ=Pr6HDQb>Ij-RP8-"
65
+ "ls=m27Ti(H?7K$h}Bnq4)aCd$+G3IAq0<TT|1aNc)e(VU;+EuTx+1SOznXErvX_W!ERB63>X"
66
+ "F7Cv7-"
67
+ "Je^w(Ghv=lEbRYLsmKH^Jq4_mKFHfT*PZcJHe+QP)Sf~XZVlcMKbaZMHeKtm#~hviq+yu*V$"
68
+ "H=EDa62gYu4cDL8oPXi<cS&5Z0k7>p7O7{J6uOB>wq>rhEZ`u|?f>E%LDHiQanmBOWJf<M@2"
69
+ "ug|^dBK+LtfLOl^Jh!Jg1JEOf~IYi;iOeeHq9`b}p0?oJ49Vchp0M<I5od0T;p`G+Vv;LsSV"
70
+ "qY1GH|#tah0qCHq}$N`=%(!k_bulWhW9T?E|^B@W4T;e=163F$G{n>Cn5a%j&|r4<G&4mWmG"
71
+ "SIf&c(uQv6+9y%^rr%G}=k@AWU6AL@?BZ8W}t;_W_@?H)By={>P)E3M@&9E=^HS+whI-"
72
+ "Y`vKLFm-U_6Uf&Vf(kgD+Iz?PbvhiI3q<OSOvUlxroyti{g2tL{|IE^uyJHHr-ysb>JiB-"
73
+ "m&+?4e9L-"
74
+ ")80B_MY6V5ILbFGqc(KnMF}o5%wi`a(Oe}W;YBPgt5+dvIP<nt2k5c>w^1J*sj!nNY*VlpV#"
75
+ "#W;>Aw_MXoLXe#f6Lr@+*>=@KwYk5u*o3!+W`lo#ZoeHe564jcoLA)N$s=aZ!jVY*RDq<9G*"
76
+ "XUloPRCqP0%3^$7t22|&Fr$(P68t^e4^kIMpwu+SQ!jg>Edapu=F-"
77
+ "hlR@4jRXqG!H|7=l|O1eZU_8_0#T2={NCwo?dT*UY&y-Xn``ia1P-"
78
+ "h^7d`2e3)ie^(!D^&8ytq;5oDV0qnmuisR(VSA-_e|4XoH#d8NtofnwdWY{&WdItc_37u-"
79
+ "YA-"
80
+ "r5cphx+0nfl9=zVi#HgQQqXb^}Mw6`VFI(>L4K;0U|gzsq<axF+wBFM6?r}?F^6<H+Z<E$<+"
81
+ "D?u&?!#hWD6PsbTFkFoME>g2Zpl!6YjFG(_fhvuvkzmfgK<u=8`>z5aG+88@gM3CDZ~Ychg%"
82
+ "Dy(j#`kV*dgI&8yM<&epkU;)9H7<R{}P8o)PGFqIlgdE4CqUd_V4gT_gJV<8Ej5>EY3`lXpX"
83
+ "!<oSxV)ARmt)qkk{yV>LVNRy%O?J~&!K8{s{vkQ@U+wBIm<gK>KWP{t7`ln);iLBLFb_IYf>"
84
+ "RWAOgf%G|!jnD1a3HT#D~h3`A|>`o@0NnnzI0C-"
85
+ "7Eypoq9$AphfG*BQOP+Ks6r&0I%YKZ+?)i0=4ejnU5~vs%%PwfsYD|SoHEP7{Dfs9l~8|nJW"
86
+ "nlw@M93))=#*f+%kx{@RGeTEFgv@eZ7S%iF6$YsZt5n5@-"
87
+ "eG_ceY^z@82&U?c%@A((JPgl`X^8`G0>GlV67PoO2kP8y2hM(6&BG8{M%&Sr~6POg|`=~FfA"
88
+ "3;Qaw*H3=7EOryiFe9F}OPhq>BCX)n)VETC>B88@w;woUx&%z8=z{hHslc2;fuyL{DAAjTjh"
89
+ "8OOwA=8B{$DnWnFIfTg67O%hRl4rG??4a_;{*g*EwcWuYeM-"
90
+ "s>vmWyq*$(;~W;ak9^`>ej$obPt-fz(M24fSy}4<hBi|@wRfP2yV&@i7wu_fU~w0^j-"
91
+ "OW<Yx;1OsVRf6OpgL{ib)Pw_e;1XMJVL6S870G<yj+J%^Y`0)3Pa^?bDg8<3tsIbg$sO1;VR"
92
+ "zyl<$rZYJ_goD-b0sfl1(X+1(u6yIrw-if6$h`J(}!7m4P$Mf`IwbXY-"
93
+ "Z^q^NaxAa?v)&eQ&m;OQkE!+)r&QAY)HbyKwv)*o?QrWpXdC*eh1KfG6n?ZZ%z74lNyoU?eJ"
94
+ "_HdI28H;+m%A|k`ljr5(hh<Fj8~b;%g$NT3cgFa1?*3Z4~D%BU4h;D-"
95
+ "N9bYC>|{qCIVG0_?!Uc|`k)JKOY}&!z2AI}S&7Jqdu8L&!t9p$S9OiZaBTsGg%nx2_arsHF*"
96
+ "0jYtu1k|TV#aYZR4V<EeAmq_zs38X$*DIIELBkrfM1jdVG!h{u9BP|K)j5x}cy^H6(wDu0$y"
97
+ "Ih3eS}RG}x9m~ajIaeF9lEbNRo*Yg+nfm%L^~Y&_O-"
98
+ "U;5+Tj#&AL^WWiA5AQ4Zi?to4jDqyw4HG~ua=14+J4O^ebrn0**x4=)TTt3gIA)TVI2%tCM%"
99
+ "dHxC)GTV1a@@&aCHWGZ|f<3ns!=cNhN{4=7mq{yuD-"
100
+ "*r?B;~kbq!4i<jis;W@_BOy1HN(9?R-~8dx+sX=61tO$K_9DD8qIB6~L-"
101
+ "ZHqZ>1EGsXZiRb91KU_8{Nxz((vcf{k8CL>vI#^NsF`R*@9RD!SMH_z&`8ucB@U7g(^z;6;1"
102
+ "0RjwU4&}VET@8PdJ&0$&`~W#>1!?KQOS>e`XI!%ibfqqrgyf-"
103
+ "3p|;fQhCG$@Jw=(lDqiK$(sk!jE63`RU--"
104
+ "%k^1W2tdkIsgk@1sWGlL^6vya6q*`(Z?f7J(?F{)YoOOL*Y!zvDFpXBU(x^egI~@lOGOd{*c"
105
+ "qo!~3b(upw~~Pr<FIkPXT4sb#!Q>sB%?JmKiYu`vHt|A=TqtW#e-"
106
+ "bIvW;L&j;Iwk0(8}x7P=q(afR{zCQng)jun<K6er2;_9^(+sy8CV@`I5l#^?Is?==y{6crG%"
107
+ "5635h7`U;p_t@Z{jU9o!HqiqPC6iYJ*)lbYgj_NPmItqiSN9YVYwY&r1DDr5gtG4p3OETNg!"
108
+ "Yzeya>IsrIUL~VJqLW>j%fyW@s=fI1tmI^OavW{NetcAXTpDrcz(ZNUfJ7`TFk!>Eh~XXYTT"
109
+ "6YAi}wwOwSx7+giX2ZgMV=u{t4i@&$dAVk(9s1NR7Xv_-#^)Vs&`@;OQh#9Su#30X)v|U%o-"
110
+ "O{zsTk^T=M5DnfY#BTZ6%(Z9YDMOY)_~QVuU5!`=ZbTRgrg|UJ7@;eaiH*X?_m&cmiGjGnLZ"
111
+ "5fN|Q^-hlcgYmI&*Xqh!12ci-"
112
+ "9~>TEZ4M|2K*$f?z^2Km($t@tpu%kMzpCRd(|GAU}z=O)yJC-"
113
+ "*t<f#uuRw)RYVat2*!C6%xwWA?BD-b_>8hBIpUp9j(hR2T~4tqIjm=bSCA!nC;)oip2GLO5|"
114
+ "~@j4(^F@-"
115
+ "ofP;6tL_{0ILV=?o_A9xs&6TE`{v)j^X<TzQ9xYS38^Xxie(d7As98=nBydO^EL+B<IPsulm"
116
+ "F9!k<Evh_$31Rf)*OE-YSc6k?9iY9PV}71uC!aha`Iek6mL?KCy><Ha(l7P5K(woA=ob8UnR"
117
+ "A%wokvP<`vp?kg@r&rr{v1$sutmUI$1pGL|#%glYTGk_h4O|pcSG}x-xh@qERz3QWauUS-"
118
+ "JiqA5^V1Z<p>P!cR@*nom#`BUJI-Co5!n^z8rwo<M(PqWR;2pz4;*+zH=2l)GV+o(Ys2jOt8"
119
+ "cOrwT3Qz(y!-LZ+SL=9JJprcju6#SqJUOUFeX?pFh$)_IMx_86$`xWy9{zHU^<HqWI=-"
120
+ "eJVqJpb6Mz+#0{wvHPqp1*cETxTpF8LY{+|ked9ABpv`<->heo{dn-"
121
+ "L8<^H(u|uvQU#K?<hw`E=qnuJdG=;39!r*_j`WyfaLk6Zk{TIZIrf0Iwf!05h|TmFfnjuF`c"
122
+ "_QrKK#SUme7NrK8zM`z>8qand9}mTp-SElmN&_h~deU{N5~6XnF}zYj2QF(g{$&n?YMmG}1n"
123
+ "b~iCrbq3p*o4T@?SUVi*>f0^OzIl2({5fAL;%9UEMs8|ClAQwcbz-"
124
+ "u4S%i8NjyY|EDeGAlms7?hE=fhIqEfzwWf{x@L9NgQ`EF!>R{#$Q50m{QIZ3UF_j!=8eJ>%Z"
125
+ "@4^H*$;3xD){&LF&sNP;TSE@SdhSt7r6LhiTjc2DEjvptL*6W4-"
126
+ "{$kArWNoL;`=ou;%2=cuv+jjFtt_f8=RdqhYn?$`Gwg4d2S(fBX_~Id;_6FfJl*_c_1U&8aL"
127
+ "tz>!9#pXF3Y$rz3mI07ig_SXti$T=7WNGqKfvNsUsJEJvrN-_xQ?OaZu)w{37VLrbTgB~_dM"
128
+ "`>u4NKJO1_(Y;+}=;LtNv(M5MSfIZ2L;!I4rZ>`f>1u@ua4p}MlF!_akbDNu#9d{maJ#5*k5"
129
+ "04-+eNVe-Ww*{)3fQYX$Xj4wMl8PbR>S2CiX235X9yog;7gyrlar#TXlvlh2&CP$85{?4O}W"
130
+ "CO}JcyWvKxyVo&8sac4Ykf|&<Td+)ZSF+ZKPv>;cfJb-GGJBK$7o81G7T%+1FTOD)<e{^<!h"
131
+ ">DxKOMP9n<yD=0PbNTOQjc!_hvb-@@6pqeuRp6UKf7Yp35tjYq6G-"
132
+ "e1c#Q**dHy3ECgeKJm_PjLpX-"
133
+ "x;#9K1y7xTs(Nmz#nUQ(ze8Jwp>poP<T+&STPfnCmEgLqtgm_yIy-C(M%D-"
134
+ ";Q*!8cKZaYZFM-"
135
+ "p|7=F^6$CBntRdVHt=AgAUnFRst8zllf$<+XSoD|8U}Dvq)>`3z?XjI}4Ka*hQxGE?tx&p1|"
136
+ "?rVr-ef3+>E_~9WFx^IPi-"
137
+ "1hOD(?BkLbZ;zZc3z;;+=ZYt40rBq4+X7p{f%|8(e6V1KH^xjq=zcl`l*Km;BOolM;F@AdZ&"
138
+ "ep#57{KGt+RUwG~i~w*O7bR^Q_Bwj3BI0X0Fd$*$Qw9youu;Giino)%xj<PBy4S0)?ltchEu"
139
+ "R=LLQ^FUj19DQeS;<LVcaRryuJ*y0t;cE9rKS~FNz+(Y+T)}CRLyfw5<6|k3{;cQs&bw`#TN"
140
+ "Bp=TN69#TNA4hkdeIO*^#`sXp*~XlmijLi>9JERA209|Cuq=UHWfkTt6~rZl4REyf{;<^TG&"
141
+ "iO8;8cG2yW9-X#Q1XF(Gnv2|MdyQT|JX6*~!);nUOguCy1?mfY?nDjiF-"
142
+ "}YIpHe^ULG6P6wdp`j3kL%j@7lfvF-MQ_Ii6UqF{E56P*V*<LUel<vsf!2~kQiU%7y;;ahs2"
143
+ "12@RH`Ag@_T^f7mM3fnP~u1uX6*uRGN)rX#q7Eu-"
144
+ "Zn)hD^%T1V$7s+3&dq2MbSFyZUIcSSBhQ`+U?Ftq|5Xf@AAt9}1co-kV?&Jx^GiK?tvIOt#c"
145
+ "fuK(c(>j`!ZWN3If$ExVzah^N<5LcD{-hv5fx8A|g|C)(Dyk^$Gm&oL*RI5_rt6;@-"
146
+ "+5=&A|+7pM#kGrICG{XyBel&@Z3v0m#vGMcBVa*u-"
147
+ "}NnN%Q>;h74k2aQ5kwpVobxPZ}bh$alG=rM3Bo<L0M}`Iz>M&Tz}_1MQpLNVqm!V(|7A(}%$"
148
+ "mvmZ=iID@Xf<#<Z{`Y65qkZHQL&7UrFXMgm}QxvdrAZ9+dzq?tSo$W_h%NB`PFIo`n2Z^%OA"
149
+ "#2Pzxqwds44p-FXxY6B(-"
150
+ "M<1EKtuoc=Zy6U)ovv4O|bd>lu{6eNj7p@)aBYny0!VzdHN1jGT;NE34%(KB%Eka?iJ({qrh"
151
+ "^riloWqwYp&5CVnYVQ9y>TRbH+vywZvKk=)kDXJ+}apQ!s4GM`sv6XL9c{gQ*oYjO;K*_m}2"
152
+ "2~u)?pxz9G~^_M*RcZyPYUu)bU<-"
153
+ "6VEo%kMvP=?toRTNP<X_$iB=O1>Zy~{*zslG<!O2)kG&LQgWoSPP@S4nSkcL6)6`ZqJ=>a{="
154
+ "8TzqKf*WfRc|_SM3|G3F0Caqxl2v@jxVFFZY6YcQ!nk5xu;AClyLI>*eQ^M#E^u=Nq1xJHX="
155
+ "NPs1PI*JSb*Kl<884-"
156
+ "ub+ZyrY&*jKJ8(O{qp=h4fdB9$#L3Rr9AJl|%C3!&eD;6*|F;b?q%|FrF^bVdVI=GEb?bUI^"
157
+ "mqB_X<h$#fYNXMok4kAV&^C#Ed*HehE<imdWgKY*N_Le?WEzIuKs4^xg`)B1JI4r+rDc}c9T"
158
+ "Wk-&DluW-PqHGfxD}o?jj?`Pkol9++8266?e68@e4tc>Fp5%(?Ki<cj32l866%VAXCqQ;{EC"
159
+ "F$aF5@WwA^9DE2tUmhKiFS>11WGQ%de~FsYf0<ioUxZ7vZ6_JSD=le}!d2G@Fz9{SWHfYVOU"
160
+ "{=MiqR$Qem@Un`yp1;fhQ%Fx_Ny|J_qn=P$^9W7>mPnk;6#cr0A=2=F6ysDaoqV>^D17y&=x"
161
+ "%BGgNj)5&QPcPWrX!jpU!XW~Ff2jue(EY}>ihPJU(X@{NTc>4&eV|UhGS+0$INXfsB3yQgA9"
162
+ "7K;omZ6DAg#x5JOb^3>j_r7QLP6Mch}jvVG$&3|#x-O?_3<@C<77`Gr6j$we}yhc#-"
163
+ ">BA7ebE<YVIc*WY$={=f-a!`xcu`39AeI-a110dzh1p>Uh!LYT1-"
164
+ "_*oV0^WOfY&ii`0H18RykTza{aO#3TsC-NCf*c-"
165
+ ";rNi&<Nzc9SbzYGko56>K>C+GhCn1Tq)$=RiEz6J-"
166
+ "`>q5jdBCfVE9nUY@my<LZ&r`Q<mt!08}zGvAR{&U3js%gg96}gf$(#K^VXw3~ELloX?<7SpG"
167
+ "Hp9g}f3r^$0J><MweG++#X5ATTEb$)gFjHtQcU+z-"
168
+ "$JR)*`+<PSTx+vzS|8IlEu5@4Cm%*Yf?BCUg8QAot^l)@xH3d7H|5-xEB#zkpHGmC$3Z7g^-"
169
+ "4defasR}u!>#&OULGQmL6z@CUe<7a-"
170
+ "LL$U${tsLmDAD{G3CqqicKP)_*u<xGk*ClN5;a1_q+DoDj-"
171
+ "!X3eF&U+fNeSNLKGxS5ubM9E97w_Pb<(<kk%wfzDca`q8l_#5ZVMDCurSx>Y>0wz!fOkGO&Z"
172
+ "q6@f=2|F5<<Q&};z1eJT!I&f|LFn?=TklvgUhMyx20@V{Xx#2qP48%+NDEm*v^OH}qz2!FeL"
173
+ "UPem(pysSN)Jn&?+A52-Jo_3Brh0$^u`q1Q#_sXIqwRCZJ<O0HKDyZDnM@{n>-ul0Zg!-"
174
+ "MQW==2__xAMo}E*<Ridy-"
175
+ "r+Cj+Toio+rD~xtuNzqXb?0#OY?iqCdAk?yrqRf1)T%>J5|)Io0c9=o9HB`oFboEC<B!f6+4"
176
+ "L%lH=Ke{0#;(ebabZDO~>A{%PhG29(m*ilSYHC>q4dv+>DulZVl+~OCS={i*%9I4sb>x*FfK"
177
+ "DV|UFG~L>GSPU=CjE^sxLEwCq1rXh3F5Wdt&R+Ry{AWKnM2`9bTNZ~(A~hkD(FrA6_Aq3T})"
178
+ "^0Ml7^6eM3h6GdEY*dwg=&m>M?jFze7gs=D&5P?8^M2(Tj+LY)Z{>>*fRNBDSgGzOJMa_x2V"
179
+ "Np5ye=Vi(AX0Gu&zJ!q=JdP}cguJm76+kf<Hdi~GAnk%u4R(yBd?@~96!X!(r}SkMn(XuDyY"
180
+ "L^z*4`Uf)-"
181
+ "z|t@FRb4IQ!>eXi?moA|Yf+)YI@|Yb!R=6PSV`lKgru6uALOiC_4_6plIE=e&domo5bhvc&5"
182
+ "X!I*Ke!V||fU@U*Jb_1+9RP5sr7yO&zbOq>nA*7>eUJBc*YLocUbv>Q*Cnh9py?v}HU*J29c"
183
+ "#EW9jW_OhUl93icW0FnpSb7MgCTzGGoNp>!D{7Mji<=ULnZy~-"
184
+ "N+qCRRIPT2k?J0+W+qr00a2%{Pynxe&=BS5fBISFGluv;O{);KfprR|6nbD2mj8h`~&7h`2T"
185
+ "S%zsvcZZ1_ix8RGv<J^U`^_sR7?QuKlUb&mbJfZsd&e+2kp{MP6H4*k8S`UfhC{a-"
186
+ "q)|4_hhLGd4W2ho2Ck-x)#_x69_lqCP@`>G1?2!B3BetG-8{NV)YpFjQ|AznS~"
190
187
  )
191
188
 
192
189
  EMPTY_XLSM_BYTES: bytes = zlib.decompress(base64.b85decode(_EMPTY_XLSM_B85))
@@ -258,6 +258,23 @@ class VBAForm:
258
258
  default_factory=lambda: [], repr=False
259
259
  )
260
260
  _header_edited: bool = field(default=False, repr=False)
261
+ _layout_dpi: int = field(default=96, init=False, repr=False)
262
+
263
+ @property
264
+ def layout_dpi(self) -> int:
265
+ """Target designer DPI for newly laid-out controls and pages (default 96).
266
+
267
+ Other DPIs use estimates scaled from measured 96-DPI font metrics.
268
+ This setting is not stored in the file and does not change existing
269
+ geometry or fonts. Set it again after reopening a form.
270
+ """
271
+ return self._layout_dpi
272
+
273
+ @layout_dpi.setter
274
+ def layout_dpi(self, value: int) -> None:
275
+ if type(value) is not int or value <= 0:
276
+ raise ValueError("layout_dpi must be a positive integer")
277
+ self._layout_dpi = value
261
278
 
262
279
  @property
263
280
  def properties_set(self) -> int:
@@ -377,7 +394,7 @@ class VBAForm:
377
394
  self._count_shape(level)
378
395
 
379
396
  font = self._font_of(level)
380
- default_w, default_h = _default_size(kind, font)
397
+ default_w, default_h = _default_size(kind, font, self.layout_dpi)
381
398
  size_w = default_w if width is None else points_to_himetric(width)
382
399
  size_h = default_h if height is None else points_to_himetric(height)
383
400
  site = _new_site(
@@ -648,17 +665,19 @@ class VBAForm:
648
665
 
649
666
  def _page_box(self, level: _Level, size: Size) -> tuple[int, int, int, int]:
650
667
  """Where the designer lays out a page of the MultiPage at ``level`` in a TabStrip of ``size``, and
651
- the page's size: two pixels inside the TabStrip's border and under its tabs, whose height follows
652
- the MultiPage's font (tests/fixtures/form_fonts.json). The designer rounds the TabStrip to whole
653
- pixels at 96 DPI and turns each pixel edge back into HIMETRIC at the TabStrip's own HIMETRIC per
654
- pixel, so the page's top moves a unit or two with the size (tests/fixtures/multipage_resize.json).
655
- Left, top, width, height, in HIMETRIC."""
656
- wide = max(1, _mul_div(size.width, 96, 2540))
657
- tall = max(1, _mul_div(size.height, 96, 2540))
658
- under = _PAGE_INSET_PX + _tab_band_px(self._multipage_font(level))
659
- left, top = _mul_div(_PAGE_INSET_PX, size.width, wide), _mul_div(under, size.height, tall)
660
- right = _mul_div(wide - _PAGE_INSET_PX, size.width, wide)
661
- bottom = _mul_div(tall - _PAGE_INSET_PX, size.height, tall)
668
+ the page's size: a scaled two-pixel inset under the tabs in the MultiPage's font.
669
+ At 96 DPI this is measured (tests/fixtures/form_fonts.json and multipage_resize.json);
670
+ other DPIs use scaled estimates. Round the TabStrip to whole target pixels and turn
671
+ each edge back into HIMETRIC at its own HIMETRIC per pixel, so the page's top
672
+ moves a unit or two with the size. Left, top, width, height, in HIMETRIC."""
673
+ dpi = self.layout_dpi
674
+ wide = max(1, _mul_div(size.width, dpi, 2540))
675
+ tall = max(1, _mul_div(size.height, dpi, 2540))
676
+ inset = _mul_div(_PAGE_INSET_PX, dpi, 96)
677
+ under = inset + _tab_band_px(self._multipage_font(level), dpi)
678
+ left, top = _mul_div(inset, size.width, wide), _mul_div(under, size.height, tall)
679
+ right = _mul_div(wide - inset, size.width, wide)
680
+ bottom = _mul_div(tall - inset, size.height, tall)
662
681
  return left, top, right - left, bottom - top
663
682
 
664
683
  def _multipage_font(self, level: _Level) -> _Font:
@@ -1567,18 +1586,22 @@ _TAB_BAND_PX: dict[tuple[str, int], int] = {
1567
1586
  }
1568
1587
 
1569
1588
 
1570
- def _tab_band_px(font: _Font) -> int:
1571
- """A tab's height in pixels for ``font``: as measured, or else estimated
1572
- from the size alone, which reproduces every Tahoma size measured and is
1573
- within a pixel of the rest."""
1589
+ def _tab_band_px(font: _Font, dpi: int = 96) -> int:
1590
+ """Measured at 96 DPI; scaled estimates elsewhere, including pixel rounding.
1591
+
1592
+ Unknown fonts use an estimated line height plus scaled tab padding.
1593
+ This is deterministic, not a query of the machine's installed fonts.
1594
+ """
1574
1595
  twips = font.size // 500
1575
1596
  measured = _TAB_BAND_PX.get((font.name.casefold(), twips))
1576
- return measured if measured is not None else round(twips / 15 * 1.2) + 6
1597
+ if measured is not None:
1598
+ return _mul_div(measured, dpi, 96)
1599
+ return round(twips / 15 * 1.2 * dpi / 96) + _mul_div(6, dpi, 96)
1577
1600
 
1578
1601
 
1579
- def _himetric_px(pixels: int) -> int:
1580
- """Pixels at 96 DPI in HIMETRIC, rounded as the designer rounds them."""
1581
- return round(pixels * 2540 / 96)
1602
+ def _himetric_px(pixels: int, dpi: int = 96) -> int:
1603
+ """Target-display pixels in HIMETRIC, with the measured 96-DPI rounding."""
1604
+ return round(pixels * 2540 / dpi)
1582
1605
 
1583
1606
 
1584
1607
  def _mul_div(number: int, numerator: int, denominator: int) -> int:
@@ -1587,13 +1610,14 @@ def _mul_div(number: int, numerator: int, denominator: int) -> int:
1587
1610
  return (2 * number * numerator + denominator) // (2 * denominator)
1588
1611
 
1589
1612
 
1590
- def _default_size(kind: str, font: _Font) -> tuple[int, int]:
1613
+ def _default_size(kind: str, font: _Font, dpi: int = 96) -> tuple[int, int]:
1591
1614
  """The size the designer gives a new control of ``kind`` on a container
1592
1615
  showing ``font``: the kind's own, but a CheckBox or OptionButton at
1593
- least 24 pixels tall and four more than a tab in its font."""
1616
+ least 24 baseline pixels tall and four more than a tab in its font.
1617
+ Baseline pixels scale from 96 DPI before rounding to target pixels."""
1594
1618
  width, height = _DEFAULT_SIZE.get(kind, _DEFAULT_SIZE["CommandButton"])
1595
1619
  if kind in _FONT_HEIGHTED:
1596
- height = _himetric_px(max(24, _tab_band_px(font) + 4))
1620
+ height = _himetric_px(max(_mul_div(24, dpi, 96), _tab_band_px(font, dpi) + _mul_div(4, dpi, 96)), dpi)
1597
1621
  return width, height
1598
1622
 
1599
1623
  # MorphData's PropMask bit 31 is reserved and MUST be 1