excel-mcp-server 2.2.2__tar.gz → 2.2.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 (228) hide show
  1. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/PKG-INFO +1 -1
  2. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/pyproject.toml +1 -1
  3. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/pyproject.toml.orig +1 -1
  4. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/consistency.py +7 -6
  5. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/extensions.py +22 -19
  6. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/opc.py +26 -14
  7. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/patch.py +3 -2
  8. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/restore.py +8 -3
  9. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/LICENSE +0 -0
  10. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/README.md +0 -0
  11. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/__init__.py +0 -0
  12. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/__main__.py +0 -0
  13. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/cells.py +0 -0
  14. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/criteria.py +0 -0
  15. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/dependencies.py +0 -0
  16. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/dynamic.py +0 -0
  17. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/engine.py +0 -0
  18. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/__init__.py +0 -0
  19. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/arrays.py +0 -0
  20. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/conditional.py +0 -0
  21. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/datetime.py +0 -0
  22. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/depreciation.py +0 -0
  23. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/distributions.py +0 -0
  24. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/financial.py +0 -0
  25. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/helpers.py +0 -0
  26. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/indirect.py +0 -0
  27. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/information.py +0 -0
  28. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/logical.py +0 -0
  29. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/lookup.py +0 -0
  30. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/math.py +0 -0
  31. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/regression.py +0 -0
  32. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/securities.py +0 -0
  33. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/statistical.py +0 -0
  34. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/subtotals.py +0 -0
  35. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/functions/text.py +0 -0
  36. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/operators.py +0 -0
  37. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/parser.py +0 -0
  38. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/r1c1.py +0 -0
  39. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/registry.py +0 -0
  40. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/scheduler.py +0 -0
  41. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/solver.py +0 -0
  42. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/steps.py +0 -0
  43. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/tablerefs.py +0 -0
  44. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/textformat.py +0 -0
  45. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/values.py +0 -0
  46. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/calc/wildcard.py +0 -0
  47. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/cell_budget.py +0 -0
  48. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/cfb.py +0 -0
  49. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/chart_roundtrip.py +0 -0
  50. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/cli.py +0 -0
  51. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/config.py +0 -0
  52. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/errors.py +0 -0
  53. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/formula_syntax.py +0 -0
  54. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/formulas.py +0 -0
  55. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/function_arguments.json +0 -0
  56. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/inputs.py +0 -0
  57. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_edit.py +0 -0
  58. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_find.py +0 -0
  59. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_lines.py +0 -0
  60. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_rows.py +0 -0
  61. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_shared.py +0 -0
  62. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_source.py +0 -0
  63. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/lazy_workbook.py +0 -0
  64. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/links.py +0 -0
  65. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/macros.py +0 -0
  66. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/__init__.py +0 -0
  67. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/calculated.py +0 -0
  68. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/cells.py +0 -0
  69. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chart_index.py +0 -0
  70. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chart_info.py +0 -0
  71. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex.py +0 -0
  72. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/box_whisker_style.xml +0 -0
  73. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/colors.xml +0 -0
  74. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/funnel_style.xml +0 -0
  75. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/histogram_style.xml +0 -0
  76. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/sunburst_style.xml +0 -0
  77. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/treemap_style.xml +0 -0
  78. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_parts/waterfall_style.xml +0 -0
  79. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/chartex_xml.py +0 -0
  80. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts.py +0 -0
  81. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_axes.py +0 -0
  82. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_check.py +0 -0
  83. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_data.py +0 -0
  84. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_look.py +0 -0
  85. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_modern.py +0 -0
  86. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_options.py +0 -0
  87. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_series.py +0 -0
  88. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/charts_style.py +0 -0
  89. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/columns.py +0 -0
  90. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/comparison.py +0 -0
  91. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/conditional.py +0 -0
  92. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/conditional_kinds.py +0 -0
  93. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/conditional_rule.py +0 -0
  94. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/conditional_x14.py +0 -0
  95. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/csv_export.py +0 -0
  96. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/csv_format.py +0 -0
  97. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/csv_import.py +0 -0
  98. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/csv_values.py +0 -0
  99. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/date_width.py +0 -0
  100. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/drawings.py +0 -0
  101. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/duplicates.py +0 -0
  102. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/files.py +0 -0
  103. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/fill.py +0 -0
  104. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/filter_criteria.py +0 -0
  105. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/filter_stored.py +0 -0
  106. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/filters.py +0 -0
  107. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/formatting.py +0 -0
  108. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/goal_seek.py +0 -0
  109. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/hyperlinks.py +0 -0
  110. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/images.py +0 -0
  111. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/inspect.py +0 -0
  112. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/layout.py +0 -0
  113. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/line_edit_objects.py +0 -0
  114. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/line_edit_rules.py +0 -0
  115. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/line_edit_styles.py +0 -0
  116. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/line_edits.py +0 -0
  117. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/names.py +0 -0
  118. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/notes.py +0 -0
  119. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/paste.py +0 -0
  120. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot.py +0 -0
  121. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_axis.py +0 -0
  122. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_cache.py +0 -0
  123. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_calc.py +0 -0
  124. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_definition.py +0 -0
  125. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_fields.py +0 -0
  126. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_groups.py +0 -0
  127. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_index.py +0 -0
  128. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_options.py +0 -0
  129. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_rebuild.py +0 -0
  130. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_records.py +0 -0
  131. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_render.py +0 -0
  132. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_showas.py +0 -0
  133. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_source.py +0 -0
  134. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_specs.py +0 -0
  135. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/pivot_values.py +0 -0
  136. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/print_setup.py +0 -0
  137. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/protection.py +0 -0
  138. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/replace.py +0 -0
  139. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/rule_clear.py +0 -0
  140. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/rules.py +0 -0
  141. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheet_copy.py +0 -0
  142. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheet_counts.py +0 -0
  143. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheet_refs.py +0 -0
  144. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheet_shapes.py +0 -0
  145. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheet_view.py +0 -0
  146. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sheets.py +0 -0
  147. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/shifting.py +0 -0
  148. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_index.py +0 -0
  149. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_manage.py +0 -0
  150. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_pivot.py +0 -0
  151. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_place.py +0 -0
  152. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_table.py +0 -0
  153. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicer_xml.py +0 -0
  154. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/slicers.py +0 -0
  155. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sorting.py +0 -0
  156. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/spans.py +0 -0
  157. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sparkline_style.py +0 -0
  158. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sparkline_xml.py +0 -0
  159. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/sparklines.py +0 -0
  160. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/spill.py +0 -0
  161. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/table_options.py +0 -0
  162. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/tables.py +0 -0
  163. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/text_split.py +0 -0
  164. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/trace.py +0 -0
  165. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/transform.py +0 -0
  166. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/used_range.py +0 -0
  167. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/vba.py +0 -0
  168. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/vba_write.py +0 -0
  169. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/workbook_rewrite.py +0 -0
  170. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/workbook_settings.py +0 -0
  171. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/operations/x14_xml.py +0 -0
  172. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/ovba.py +0 -0
  173. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/ovba_compress.py +0 -0
  174. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/ovba_write.py +0 -0
  175. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/__init__.py +0 -0
  176. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/anchors.py +0 -0
  177. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/arrays.py +0 -0
  178. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/capture.py +0 -0
  179. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/capture_sheet.py +0 -0
  180. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/guards.py +0 -0
  181. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/lazy_records.py +0 -0
  182. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/lines.py +0 -0
  183. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/metadata.py +0 -0
  184. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/model.py +0 -0
  185. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/pivot_records.py +0 -0
  186. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/pivots.py +0 -0
  187. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/properties.py +0 -0
  188. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/reader.py +0 -0
  189. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/references.py +0 -0
  190. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/restore_sheet.py +0 -0
  191. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/scan.py +0 -0
  192. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/shape_names.py +0 -0
  193. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/package/vml.py +0 -0
  194. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/paths.py +0 -0
  195. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/plain_refs.py +0 -0
  196. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/py.typed +0 -0
  197. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/refs.py +0 -0
  198. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/rewrite.py +0 -0
  199. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/__init__.py +0 -0
  200. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/annotation_tools.py +0 -0
  201. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/areas.py +0 -0
  202. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/csv_tools.py +0 -0
  203. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/data_tools.py +0 -0
  204. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/format_tools.py +0 -0
  205. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/formula_tools.py +0 -0
  206. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/http.py +0 -0
  207. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/image_tools.py +0 -0
  208. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/object_tools.py +0 -0
  209. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/params.py +0 -0
  210. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/pivot_tools.py +0 -0
  211. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/registry.py +0 -0
  212. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/results.py +0 -0
  213. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/sheet_tools.py +0 -0
  214. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/slicer_tools.py +0 -0
  215. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/validation.py +0 -0
  216. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/vba_tools.py +0 -0
  217. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/vba_write_tools.py +0 -0
  218. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/server/workbook_tools.py +0 -0
  219. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/spill.py +0 -0
  220. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/structured.py +0 -0
  221. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/text.py +0 -0
  222. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/upload_links.py +0 -0
  223. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/upload_scan.py +0 -0
  224. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/values.py +0 -0
  225. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/workspace.py +0 -0
  226. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/xlfn.py +0 -0
  227. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/xlm.py +0 -0
  228. {excel_mcp_server-2.2.2 → excel_mcp_server-2.2.3}/src/excel_mcp/zip_limits.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: excel-mcp-server
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: MCP server for creating, reading and editing Excel workbooks without Microsoft Excel
5
5
  Keywords: mcp,mcp-server,model-context-protocol,excel,xlsx,xlsm,spreadsheet,openpyxl,charts,pivot-table,formulas,vba,llm,ai,claude,cursor
6
6
  Author: Haris Musa
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "excel-mcp-server"
3
- version = "2.2.2"
3
+ version = "2.2.3"
4
4
  description = "MCP server for creating, reading and editing Excel workbooks without Microsoft Excel"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "excel-mcp-server"
3
- version = "2.2.2"
3
+ version = "2.2.3"
4
4
  description = "MCP server for creating, reading and editing Excel workbooks without Microsoft Excel"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -27,7 +27,8 @@ _CACHE_LISTS = {
27
27
  }
28
28
  _SLICER_REFERENCE = re.compile(r'<(?:[\w.-]+:)?(?:slicer|timeline)\b[^>]*?\bcache="([^"]*)"')
29
29
  PIVOT_ENTRY = re.compile(r"<(?:[\w.-]+:)?pivotTable\b[^>]*/>")
30
- _CACHE_ENTRY = r'<(?:[\w.-]+:)?(?:slicerCache|timelineCacheRef)\b[^>]*?\b[\w.-]+:id="{id}"[^>]*/>'
30
+ _CACHE_ENTRY = re.compile(r"<(?:[\w.-]+:)?(?:slicerCache|timelineCacheRef)\b[^>]*/>")
31
+ _RELATIONSHIP_ID = re.compile(r'\b[\w.-]+:id="([^"]*)"')
31
32
 
32
33
 
33
34
  def cache_name(part: Part) -> str:
@@ -80,11 +81,11 @@ def without_caches(
80
81
  and link.target.content_type in _CACHES
81
82
  and cache_name(link.target) in dropped
82
83
  }
83
- kept = []
84
- for text in texts:
85
- for identifier in gone:
86
- text = re.sub(_CACHE_ENTRY.format(id=re.escape(identifier)), "", text)
87
- kept.append(text)
84
+
85
+ def entry(match: re.Match[str]) -> str:
86
+ return "" if gone.intersection(_RELATIONSHIP_ID.findall(match[0])) else match[0]
87
+
88
+ kept = [_CACHE_ENTRY.sub(entry, text) for text in texts] if gone else texts
88
89
  return [link for link in links if link.id not in gone], kept
89
90
 
90
91
 
@@ -41,21 +41,27 @@ class Rewriter(Protocol):
41
41
 
42
42
 
43
43
  _SPARKLINE = re.compile(r"<x14:sparkline>.*?</x14:sparkline>", re.S)
44
+ # An element is its start tag, then either "/>" or its content up to its end tag. Written
45
+ # like this, a self-closing element never makes the match run on to some later end tag, so
46
+ # a document of many such elements is scanned once and not once per element.
44
47
  _EMPTY_GROUP = re.compile(
45
- r"<x14:sparklineGroup\b[^>]*>(?:(?!<x14:sparkline>).)*?</x14:sparklineGroup>", re.S
48
+ r"<x14:sparklineGroup\b[^>]*?(?:/>|>(?:(?!<x14:sparkline>).)*?</x14:sparklineGroup>)", re.S
46
49
  )
47
- _RULE_GROUP = re.compile(r"<x14:conditionalFormatting\b[^>]*>.*?</x14:conditionalFormatting>", re.S)
48
- _VALIDATION = re.compile(r"<x14:dataValidation\b[^>]*>.*?</x14:dataValidation>", re.S)
50
+ _RULE_GROUP = re.compile(
51
+ r"<x14:conditionalFormatting\b[^>]*?(?:/>|>.*?</x14:conditionalFormatting>)", re.S
52
+ )
53
+ _RULE = re.compile(r"<x14:cfRule\b[^>]*?(?:/>|>.*?</x14:cfRule>)", re.S)
54
+ _VALIDATION = re.compile(r"<x14:dataValidation\b[^>]*?(?:/>|>.*?</x14:dataValidation>)", re.S)
49
55
  _DATED_GROUP = re.compile(
50
- r"(<x14:sparklineGroup(?!s)[^>]*>(?:(?!<x14:sparklines>).)*?)<xm:f>([^<]*)</xm:f>(<x14:sparklines>)",
56
+ r"(<x14:sparklineGroup(?!s)[^>]*(?<!/)>(?:(?!<x14:sparklines>|</x14:sparklineGroup>).)*?)"
57
+ r"<xm:f>([^<]*)</xm:f>(<x14:sparklines>)",
51
58
  re.S,
52
59
  )
53
60
  _GROUP_DATES = re.compile(r"<xm:f>([^<]*)</xm:f>(?=<x14:sparklines>)")
54
61
  _RANGE = re.compile(r"<xm:sqref>([^<]*)</xm:sqref>")
55
62
  _FORMULA = re.compile(r"<xm:f>([^<]*)</xm:f>")
56
- _FORMULA_ITEM = re.compile(
57
- r"<x14:cfRule\b.*?</x14:cfRule>|<x14:dataValidation\b.*?</x14:dataValidation>", re.S
58
- )
63
+ _FORMULA_ITEM = re.compile(f"{_RULE.pattern}|{_VALIDATION.pattern}", re.S)
64
+ _RULE_ID_ATTRIBUTE = re.compile(r'\bid="([^"]*)"')
59
65
  _GUID = re.compile(r'(<x14:id>|\b(?:xr2:uid|id)=")(\{[0-9A-Fa-f-]{36}\})')
60
66
  _CELL = re.compile(r"(\$?)\b([A-Z]{1,3})(\$?)(\d+)\b(?![!(\w])")
61
67
 
@@ -196,21 +202,18 @@ def rule_sub(xml: str, rule: Callable[[str], str]) -> str:
196
202
 
197
203
 
198
204
  def without_rules(extensions: dict[str, str], identifiers: set[str]) -> None:
199
- """Remove the Excel 2010 conditional format rules with these ids (``{GUID}``)."""
205
+ """Remove the Excel 2010 conditional format rules with these ids (``{GUID}``), and the
206
+ groups left without a rule."""
200
207
  xml = extensions.get(CONDITIONAL_FORMATS)
201
208
  if xml is None:
202
209
  return
203
- for identifier in identifiers:
204
- pattern = (
205
- rf'<x14:cfRule\b(?=[^>]*\bid="{re.escape(identifier)}")'
206
- r"(?:[^>]*/>|[^>]*>.*?</x14:cfRule>)"
207
- )
208
- xml = re.sub(pattern, "", xml, flags=re.S)
209
- emptied = (
210
- r"<x14:conditionalFormatting\b[^>]*>(?:(?!<x14:cfRule\b).)*?"
211
- r"</x14:conditionalFormatting>"
212
- )
213
- xml = re.sub(emptied, "", xml, flags=re.S)
210
+
211
+ def dropped(rule: re.Match[str]) -> str:
212
+ start_tag = rule[0][: rule[0].index(">") + 1]
213
+ return "" if identifiers.intersection(_RULE_ID_ATTRIBUTE.findall(start_tag)) else rule[0]
214
+
215
+ xml = _RULE.sub(dropped, xml)
216
+ xml = _RULE_GROUP.sub(lambda group: group[0] if "<x14:cfRule" in group[0] else "", xml)
214
217
  if "<x14:cfRule" in xml:
215
218
  extensions[CONDITIONAL_FORMATS] = xml
216
219
  else:
@@ -4,7 +4,9 @@ import io
4
4
  import posixpath
5
5
  import re
6
6
  import zipfile
7
+ from collections.abc import Callable
7
8
  from dataclasses import dataclass
9
+ from itertools import count
8
10
  from xml.sax.saxutils import quoteattr
9
11
 
10
12
  from excel_mcp.errors import WorkbookError
@@ -75,15 +77,25 @@ def write_rels(rels: list[Rel]) -> bytes:
75
77
  return (XML_DECLARATION + "".join(lines)).encode()
76
78
 
77
79
 
78
- def free_id(rels: list[Rel], wanted: str) -> str:
79
- """``wanted`` if it is a free ``rIdN``, else the first free one."""
80
+ def free_ids(rels: list[Rel]) -> Callable[[str], str]:
81
+ """A function that gives, for each id wanted, that id if it is a free ``rIdN`` and else the
82
+ first free one, and then counts it as taken. Many calls cost no more than one scan."""
80
83
  taken = {rel.id for rel in rels}
81
- if re.fullmatch(r"rId\d+", wanted) and wanted not in taken:
82
- return wanted
83
- number = 1
84
- while f"rId{number}" in taken:
85
- number += 1
86
- return f"rId{number}"
84
+ numbers = count(1)
85
+
86
+ def allocate(wanted: str) -> str:
87
+ if re.fullmatch(r"rId\d+", wanted) and wanted not in taken:
88
+ chosen = wanted
89
+ else:
90
+ chosen = next(f"rId{n}" for n in numbers if f"rId{n}" not in taken)
91
+ taken.add(chosen)
92
+ return chosen
93
+
94
+ return allocate
95
+
96
+
97
+ def free_id(rels: list[Rel], wanted: str) -> str:
98
+ return free_ids(rels)(wanted)
87
99
 
88
100
 
89
101
  class ContentTypes:
@@ -135,15 +147,16 @@ class Package:
135
147
 
136
148
  def __init__(self, data: bytes) -> None:
137
149
  self._source = zipfile.ZipFile(io.BytesIO(data))
150
+ self._source_names = set(self._source.namelist())
138
151
  self._changes: dict[str, bytes] = {}
139
152
  self._rels: dict[str, list[Rel]] = {}
140
153
  self.content_types = ContentTypes(self.read(CONTENT_TYPES))
141
154
 
142
155
  def names(self) -> set[str]:
143
- return set(self._source.namelist()) | set(self._changes)
156
+ return self._source_names | set(self._changes)
144
157
 
145
158
  def exists(self, name: str) -> bool:
146
- return name in self._changes or name in self._source.namelist()
159
+ return name in self._changes or name in self._source_names
147
160
 
148
161
  def read(self, name: str) -> bytes:
149
162
  if name in self._changes:
@@ -162,13 +175,12 @@ class Package:
162
175
 
163
176
  def unique_name(self, wanted: str) -> str:
164
177
  """``wanted``, or the same name with the next free number in it."""
165
- taken = self.names()
166
- if wanted not in taken:
178
+ if not self.exists(wanted):
167
179
  return wanted
168
180
  match = re.fullmatch(r"(.*?)(\d*)(\.[^./]*)?", wanted)
169
181
  stem, number, extension = match.groups() if match else (wanted, "", "")
170
182
  counter = int(number or 0) + 1
171
- while f"{stem}{counter}{extension or ''}" in taken:
183
+ while self.exists(f"{stem}{counter}{extension or ''}"):
172
184
  counter += 1
173
185
  return f"{stem}{counter}{extension or ''}"
174
186
 
@@ -189,6 +201,6 @@ class Package:
189
201
  elif content:
190
202
  target.writestr(name, content)
191
203
  for name, content in self._changes.items():
192
- if content and name not in self._source.namelist():
204
+ if content and name not in self._source_names:
193
205
  target.writestr(name, content)
194
206
  return output.getvalue()
@@ -150,11 +150,12 @@ def patch_cells(data: bytes, edits: dict[str, CellEdit]) -> bytes:
150
150
  """Rewrite chosen cells of ``sheetData``; an edit gets a cell's attributes and its content."""
151
151
  if not edits:
152
152
  return data
153
- names = b"|".join(re.escape(name.encode()) for name in edits)
154
- cell = re.compile(rb'<c r="(' + names + rb')"([^>]*?)(?:/>|>(.*?)</c>)', re.S)
153
+ cell = re.compile(rb'<c r="([^"]*)"([^>]*?)(?:/>|>(.*?)</c>)', re.S)
155
154
 
156
155
  def rewrite(match: re.Match[bytes]) -> bytes:
157
156
  coordinate = match[1].decode()
157
+ if coordinate not in edits:
158
+ return match[0]
158
159
  attributes, body = edits[coordinate](match[2].decode(), (match[3] or b"").decode())
159
160
  start = f'<c r="{coordinate}"{attributes}'
160
161
  return f"{start}>{body}</c>".encode() if body else f"{start}/>".encode()
@@ -14,7 +14,7 @@ from excel_mcp.package.model import (
14
14
  state_of,
15
15
  workbook_sheets,
16
16
  )
17
- from excel_mcp.package.opc import Package, Rel, free_id
17
+ from excel_mcp.package.opc import Package, Rel, free_ids
18
18
  from excel_mcp.package.patch import WORKBOOK_ORDER, append_to_root, insertions, splice
19
19
  from excel_mcp.package.restore_sheet import restore_sheet
20
20
  from excel_mcp.package.scan import attributes, rel_id, remap_relationship_ids, scan, tags
@@ -103,13 +103,18 @@ class Restorer:
103
103
  ) -> list[str]:
104
104
  """Add relationships to a part that is being merged into, and renumber the XML to match."""
105
105
  rels = self.package.rels(owner)
106
+ free_id = free_ids(rels)
107
+ known: dict[tuple[str, str], Rel] = {}
108
+ for rel in rels:
109
+ known.setdefault((rel.type, rel.target), rel)
106
110
  mapping: dict[str, str] = {}
107
111
  for link in links:
108
112
  rel = Rel(link.id, link.type, self.target(link), isinstance(link.target, str))
109
- existing = next((r for r in rels if (r.type, r.target) == (rel.type, rel.target)), None)
113
+ existing = known.get((rel.type, rel.target))
110
114
  if existing is None:
111
- rel.id = free_id(rels, link.id)
115
+ rel.id = free_id(link.id)
112
116
  rels.append(rel)
117
+ known[rel.type, rel.target] = rel
113
118
  mapping[link.id] = (existing or rel).id
114
119
  return [remap_relationship_ids(text, mapping, scope) for text in texts]
115
120