paper-xlsx 0.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.
Files changed (237) hide show
  1. paper_xlsx-0.1.0/AUTHORS.rst +98 -0
  2. paper_xlsx-0.1.0/LICENCE.rst +24 -0
  3. paper_xlsx-0.1.0/MANIFEST.in +7 -0
  4. paper_xlsx-0.1.0/PKG-INFO +190 -0
  5. paper_xlsx-0.1.0/README.rst +149 -0
  6. paper_xlsx-0.1.0/openpyxl/__init__.py +37 -0
  7. paper_xlsx-0.1.0/openpyxl/_constants.py +13 -0
  8. paper_xlsx-0.1.0/openpyxl/cell/__init__.py +4 -0
  9. paper_xlsx-0.1.0/openpyxl/cell/_writer.py +136 -0
  10. paper_xlsx-0.1.0/openpyxl/cell/cell.py +398 -0
  11. paper_xlsx-0.1.0/openpyxl/cell/read_only.py +136 -0
  12. paper_xlsx-0.1.0/openpyxl/cell/rich_text.py +202 -0
  13. paper_xlsx-0.1.0/openpyxl/cell/text.py +184 -0
  14. paper_xlsx-0.1.0/openpyxl/chart/_3d.py +105 -0
  15. paper_xlsx-0.1.0/openpyxl/chart/__init__.py +19 -0
  16. paper_xlsx-0.1.0/openpyxl/chart/_chart.py +227 -0
  17. paper_xlsx-0.1.0/openpyxl/chart/area_chart.py +106 -0
  18. paper_xlsx-0.1.0/openpyxl/chart/axis.py +401 -0
  19. paper_xlsx-0.1.0/openpyxl/chart/bar_chart.py +144 -0
  20. paper_xlsx-0.1.0/openpyxl/chart/bubble_chart.py +67 -0
  21. paper_xlsx-0.1.0/openpyxl/chart/chartspace.py +195 -0
  22. paper_xlsx-0.1.0/openpyxl/chart/data_source.py +246 -0
  23. paper_xlsx-0.1.0/openpyxl/chart/descriptors.py +43 -0
  24. paper_xlsx-0.1.0/openpyxl/chart/error_bar.py +62 -0
  25. paper_xlsx-0.1.0/openpyxl/chart/label.py +127 -0
  26. paper_xlsx-0.1.0/openpyxl/chart/layout.py +74 -0
  27. paper_xlsx-0.1.0/openpyxl/chart/legend.py +75 -0
  28. paper_xlsx-0.1.0/openpyxl/chart/line_chart.py +129 -0
  29. paper_xlsx-0.1.0/openpyxl/chart/marker.py +90 -0
  30. paper_xlsx-0.1.0/openpyxl/chart/picture.py +35 -0
  31. paper_xlsx-0.1.0/openpyxl/chart/pie_chart.py +177 -0
  32. paper_xlsx-0.1.0/openpyxl/chart/pivot.py +65 -0
  33. paper_xlsx-0.1.0/openpyxl/chart/plotarea.py +162 -0
  34. paper_xlsx-0.1.0/openpyxl/chart/print_settings.py +57 -0
  35. paper_xlsx-0.1.0/openpyxl/chart/radar_chart.py +55 -0
  36. paper_xlsx-0.1.0/openpyxl/chart/reader.py +32 -0
  37. paper_xlsx-0.1.0/openpyxl/chart/reference.py +124 -0
  38. paper_xlsx-0.1.0/openpyxl/chart/scatter_chart.py +53 -0
  39. paper_xlsx-0.1.0/openpyxl/chart/series.py +197 -0
  40. paper_xlsx-0.1.0/openpyxl/chart/series_factory.py +41 -0
  41. paper_xlsx-0.1.0/openpyxl/chart/shapes.py +89 -0
  42. paper_xlsx-0.1.0/openpyxl/chart/stock_chart.py +54 -0
  43. paper_xlsx-0.1.0/openpyxl/chart/surface_chart.py +119 -0
  44. paper_xlsx-0.1.0/openpyxl/chart/text.py +78 -0
  45. paper_xlsx-0.1.0/openpyxl/chart/title.py +76 -0
  46. paper_xlsx-0.1.0/openpyxl/chart/trendline.py +98 -0
  47. paper_xlsx-0.1.0/openpyxl/chart/updown_bars.py +31 -0
  48. paper_xlsx-0.1.0/openpyxl/chartsheet/__init__.py +3 -0
  49. paper_xlsx-0.1.0/openpyxl/chartsheet/chartsheet.py +109 -0
  50. paper_xlsx-0.1.0/openpyxl/chartsheet/custom.py +61 -0
  51. paper_xlsx-0.1.0/openpyxl/chartsheet/properties.py +28 -0
  52. paper_xlsx-0.1.0/openpyxl/chartsheet/protection.py +41 -0
  53. paper_xlsx-0.1.0/openpyxl/chartsheet/publish.py +58 -0
  54. paper_xlsx-0.1.0/openpyxl/chartsheet/relation.py +97 -0
  55. paper_xlsx-0.1.0/openpyxl/chartsheet/views.py +51 -0
  56. paper_xlsx-0.1.0/openpyxl/comments/__init__.py +4 -0
  57. paper_xlsx-0.1.0/openpyxl/comments/author.py +21 -0
  58. paper_xlsx-0.1.0/openpyxl/comments/comment_sheet.py +211 -0
  59. paper_xlsx-0.1.0/openpyxl/comments/comments.py +62 -0
  60. paper_xlsx-0.1.0/openpyxl/comments/shape_writer.py +112 -0
  61. paper_xlsx-0.1.0/openpyxl/compat/__init__.py +54 -0
  62. paper_xlsx-0.1.0/openpyxl/compat/abc.py +8 -0
  63. paper_xlsx-0.1.0/openpyxl/compat/numbers.py +43 -0
  64. paper_xlsx-0.1.0/openpyxl/compat/product.py +17 -0
  65. paper_xlsx-0.1.0/openpyxl/compat/singleton.py +40 -0
  66. paper_xlsx-0.1.0/openpyxl/compat/strings.py +25 -0
  67. paper_xlsx-0.1.0/openpyxl/descriptors/__init__.py +58 -0
  68. paper_xlsx-0.1.0/openpyxl/descriptors/base.py +272 -0
  69. paper_xlsx-0.1.0/openpyxl/descriptors/container.py +41 -0
  70. paper_xlsx-0.1.0/openpyxl/descriptors/excel.py +112 -0
  71. paper_xlsx-0.1.0/openpyxl/descriptors/namespace.py +12 -0
  72. paper_xlsx-0.1.0/openpyxl/descriptors/nested.py +129 -0
  73. paper_xlsx-0.1.0/openpyxl/descriptors/sequence.py +136 -0
  74. paper_xlsx-0.1.0/openpyxl/descriptors/serialisable.py +240 -0
  75. paper_xlsx-0.1.0/openpyxl/descriptors/slots.py +18 -0
  76. paper_xlsx-0.1.0/openpyxl/drawing/__init__.py +4 -0
  77. paper_xlsx-0.1.0/openpyxl/drawing/colors.py +435 -0
  78. paper_xlsx-0.1.0/openpyxl/drawing/connector.py +144 -0
  79. paper_xlsx-0.1.0/openpyxl/drawing/drawing.py +92 -0
  80. paper_xlsx-0.1.0/openpyxl/drawing/effect.py +407 -0
  81. paper_xlsx-0.1.0/openpyxl/drawing/fill.py +425 -0
  82. paper_xlsx-0.1.0/openpyxl/drawing/geometry.py +584 -0
  83. paper_xlsx-0.1.0/openpyxl/drawing/graphic.py +177 -0
  84. paper_xlsx-0.1.0/openpyxl/drawing/image.py +65 -0
  85. paper_xlsx-0.1.0/openpyxl/drawing/line.py +144 -0
  86. paper_xlsx-0.1.0/openpyxl/drawing/picture.py +144 -0
  87. paper_xlsx-0.1.0/openpyxl/drawing/properties.py +174 -0
  88. paper_xlsx-0.1.0/openpyxl/drawing/relation.py +17 -0
  89. paper_xlsx-0.1.0/openpyxl/drawing/spreadsheet_drawing.py +382 -0
  90. paper_xlsx-0.1.0/openpyxl/drawing/text.py +717 -0
  91. paper_xlsx-0.1.0/openpyxl/drawing/xdr.py +33 -0
  92. paper_xlsx-0.1.0/openpyxl/errors.py +102 -0
  93. paper_xlsx-0.1.0/openpyxl/formatting/__init__.py +3 -0
  94. paper_xlsx-0.1.0/openpyxl/formatting/formatting.py +114 -0
  95. paper_xlsx-0.1.0/openpyxl/formatting/rule.py +291 -0
  96. paper_xlsx-0.1.0/openpyxl/formula/__init__.py +3 -0
  97. paper_xlsx-0.1.0/openpyxl/formula/catalog.py +124 -0
  98. paper_xlsx-0.1.0/openpyxl/formula/lint.py +269 -0
  99. paper_xlsx-0.1.0/openpyxl/formula/tokenizer.py +446 -0
  100. paper_xlsx-0.1.0/openpyxl/formula/translate.py +166 -0
  101. paper_xlsx-0.1.0/openpyxl/oracle.py +1031 -0
  102. paper_xlsx-0.1.0/openpyxl/package/__init__.py +29 -0
  103. paper_xlsx-0.1.0/openpyxl/package/cells.py +112 -0
  104. paper_xlsx-0.1.0/openpyxl/package/diff.py +177 -0
  105. paper_xlsx-0.1.0/openpyxl/packaging/__init__.py +3 -0
  106. paper_xlsx-0.1.0/openpyxl/packaging/core.py +115 -0
  107. paper_xlsx-0.1.0/openpyxl/packaging/custom.py +289 -0
  108. paper_xlsx-0.1.0/openpyxl/packaging/extended.py +137 -0
  109. paper_xlsx-0.1.0/openpyxl/packaging/interface.py +56 -0
  110. paper_xlsx-0.1.0/openpyxl/packaging/manifest.py +194 -0
  111. paper_xlsx-0.1.0/openpyxl/packaging/relationship.py +158 -0
  112. paper_xlsx-0.1.0/openpyxl/packaging/workbook.py +185 -0
  113. paper_xlsx-0.1.0/openpyxl/pivot/__init__.py +1 -0
  114. paper_xlsx-0.1.0/openpyxl/pivot/cache.py +965 -0
  115. paper_xlsx-0.1.0/openpyxl/pivot/fields.py +326 -0
  116. paper_xlsx-0.1.0/openpyxl/pivot/record.py +111 -0
  117. paper_xlsx-0.1.0/openpyxl/pivot/table.py +1261 -0
  118. paper_xlsx-0.1.0/openpyxl/preserve/__init__.py +50 -0
  119. paper_xlsx-0.1.0/openpyxl/preserve/chartpatch.py +544 -0
  120. paper_xlsx-0.1.0/openpyxl/preserve/comments.py +125 -0
  121. paper_xlsx-0.1.0/openpyxl/preserve/crosscheck.py +159 -0
  122. paper_xlsx-0.1.0/openpyxl/preserve/crosspart.py +668 -0
  123. paper_xlsx-0.1.0/openpyxl/preserve/diffreport.py +145 -0
  124. paper_xlsx-0.1.0/openpyxl/preserve/drawings.py +413 -0
  125. paper_xlsx-0.1.0/openpyxl/preserve/emit.py +165 -0
  126. paper_xlsx-0.1.0/openpyxl/preserve/hygiene.py +382 -0
  127. paper_xlsx-0.1.0/openpyxl/preserve/inventory.py +192 -0
  128. paper_xlsx-0.1.0/openpyxl/preserve/ledger.py +1145 -0
  129. paper_xlsx-0.1.0/openpyxl/preserve/lifecycle.py +257 -0
  130. paper_xlsx-0.1.0/openpyxl/preserve/locate.py +198 -0
  131. paper_xlsx-0.1.0/openpyxl/preserve/modelmap.py +126 -0
  132. paper_xlsx-0.1.0/openpyxl/preserve/perception.py +415 -0
  133. paper_xlsx-0.1.0/openpyxl/preserve/receipts.py +108 -0
  134. paper_xlsx-0.1.0/openpyxl/preserve/regions.py +306 -0
  135. paper_xlsx-0.1.0/openpyxl/preserve/rewrite.py +324 -0
  136. paper_xlsx-0.1.0/openpyxl/preserve/saver.py +1128 -0
  137. paper_xlsx-0.1.0/openpyxl/preserve/splice.py +528 -0
  138. paper_xlsx-0.1.0/openpyxl/preserve/structural.py +616 -0
  139. paper_xlsx-0.1.0/openpyxl/preserve/styletrans.py +138 -0
  140. paper_xlsx-0.1.0/openpyxl/preserve/styleverbs.py +108 -0
  141. paper_xlsx-0.1.0/openpyxl/preserve/tables.py +424 -0
  142. paper_xlsx-0.1.0/openpyxl/preserve/x14.py +248 -0
  143. paper_xlsx-0.1.0/openpyxl/preserve/xmlscan.py +514 -0
  144. paper_xlsx-0.1.0/openpyxl/preserve/zipio.py +219 -0
  145. paper_xlsx-0.1.0/openpyxl/reader/__init__.py +1 -0
  146. paper_xlsx-0.1.0/openpyxl/reader/drawings.py +76 -0
  147. paper_xlsx-0.1.0/openpyxl/reader/excel.py +528 -0
  148. paper_xlsx-0.1.0/openpyxl/reader/strings.py +44 -0
  149. paper_xlsx-0.1.0/openpyxl/reader/workbook.py +133 -0
  150. paper_xlsx-0.1.0/openpyxl/styles/__init__.py +11 -0
  151. paper_xlsx-0.1.0/openpyxl/styles/alignment.py +62 -0
  152. paper_xlsx-0.1.0/openpyxl/styles/borders.py +103 -0
  153. paper_xlsx-0.1.0/openpyxl/styles/builtins.py +1397 -0
  154. paper_xlsx-0.1.0/openpyxl/styles/cell_style.py +206 -0
  155. paper_xlsx-0.1.0/openpyxl/styles/colors.py +172 -0
  156. paper_xlsx-0.1.0/openpyxl/styles/differential.py +95 -0
  157. paper_xlsx-0.1.0/openpyxl/styles/fills.py +224 -0
  158. paper_xlsx-0.1.0/openpyxl/styles/fonts.py +113 -0
  159. paper_xlsx-0.1.0/openpyxl/styles/named_styles.py +282 -0
  160. paper_xlsx-0.1.0/openpyxl/styles/numbers.py +200 -0
  161. paper_xlsx-0.1.0/openpyxl/styles/protection.py +17 -0
  162. paper_xlsx-0.1.0/openpyxl/styles/proxy.py +62 -0
  163. paper_xlsx-0.1.0/openpyxl/styles/styleable.py +156 -0
  164. paper_xlsx-0.1.0/openpyxl/styles/stylesheet.py +274 -0
  165. paper_xlsx-0.1.0/openpyxl/styles/table.py +94 -0
  166. paper_xlsx-0.1.0/openpyxl/utils/__init__.py +17 -0
  167. paper_xlsx-0.1.0/openpyxl/utils/bound_dictionary.py +26 -0
  168. paper_xlsx-0.1.0/openpyxl/utils/cell.py +240 -0
  169. paper_xlsx-0.1.0/openpyxl/utils/dataframe.py +87 -0
  170. paper_xlsx-0.1.0/openpyxl/utils/datetime.py +140 -0
  171. paper_xlsx-0.1.0/openpyxl/utils/escape.py +43 -0
  172. paper_xlsx-0.1.0/openpyxl/utils/exceptions.py +34 -0
  173. paper_xlsx-0.1.0/openpyxl/utils/formulas.py +24 -0
  174. paper_xlsx-0.1.0/openpyxl/utils/indexed_list.py +49 -0
  175. paper_xlsx-0.1.0/openpyxl/utils/inference.py +60 -0
  176. paper_xlsx-0.1.0/openpyxl/utils/protection.py +22 -0
  177. paper_xlsx-0.1.0/openpyxl/utils/units.py +108 -0
  178. paper_xlsx-0.1.0/openpyxl/workbook/__init__.py +4 -0
  179. paper_xlsx-0.1.0/openpyxl/workbook/_writer.py +197 -0
  180. paper_xlsx-0.1.0/openpyxl/workbook/child.py +168 -0
  181. paper_xlsx-0.1.0/openpyxl/workbook/defined_name.py +189 -0
  182. paper_xlsx-0.1.0/openpyxl/workbook/external_link/__init__.py +3 -0
  183. paper_xlsx-0.1.0/openpyxl/workbook/external_link/external.py +190 -0
  184. paper_xlsx-0.1.0/openpyxl/workbook/external_reference.py +18 -0
  185. paper_xlsx-0.1.0/openpyxl/workbook/function_group.py +36 -0
  186. paper_xlsx-0.1.0/openpyxl/workbook/properties.py +151 -0
  187. paper_xlsx-0.1.0/openpyxl/workbook/protection.py +163 -0
  188. paper_xlsx-0.1.0/openpyxl/workbook/smart_tags.py +56 -0
  189. paper_xlsx-0.1.0/openpyxl/workbook/views.py +155 -0
  190. paper_xlsx-0.1.0/openpyxl/workbook/web.py +98 -0
  191. paper_xlsx-0.1.0/openpyxl/workbook/workbook.py +921 -0
  192. paper_xlsx-0.1.0/openpyxl/worksheet/__init__.py +1 -0
  193. paper_xlsx-0.1.0/openpyxl/worksheet/_read_only.py +190 -0
  194. paper_xlsx-0.1.0/openpyxl/worksheet/_reader.py +480 -0
  195. paper_xlsx-0.1.0/openpyxl/worksheet/_write_only.py +159 -0
  196. paper_xlsx-0.1.0/openpyxl/worksheet/_writer.py +390 -0
  197. paper_xlsx-0.1.0/openpyxl/worksheet/cell_range.py +512 -0
  198. paper_xlsx-0.1.0/openpyxl/worksheet/cell_watch.py +34 -0
  199. paper_xlsx-0.1.0/openpyxl/worksheet/controls.py +107 -0
  200. paper_xlsx-0.1.0/openpyxl/worksheet/copier.py +70 -0
  201. paper_xlsx-0.1.0/openpyxl/worksheet/custom.py +35 -0
  202. paper_xlsx-0.1.0/openpyxl/worksheet/datavalidation.py +202 -0
  203. paper_xlsx-0.1.0/openpyxl/worksheet/dimensions.py +306 -0
  204. paper_xlsx-0.1.0/openpyxl/worksheet/drawing.py +14 -0
  205. paper_xlsx-0.1.0/openpyxl/worksheet/errors.py +93 -0
  206. paper_xlsx-0.1.0/openpyxl/worksheet/filters.py +486 -0
  207. paper_xlsx-0.1.0/openpyxl/worksheet/formula.py +51 -0
  208. paper_xlsx-0.1.0/openpyxl/worksheet/header_footer.py +270 -0
  209. paper_xlsx-0.1.0/openpyxl/worksheet/hyperlink.py +46 -0
  210. paper_xlsx-0.1.0/openpyxl/worksheet/merge.py +141 -0
  211. paper_xlsx-0.1.0/openpyxl/worksheet/ole.py +133 -0
  212. paper_xlsx-0.1.0/openpyxl/worksheet/page.py +174 -0
  213. paper_xlsx-0.1.0/openpyxl/worksheet/pagebreak.py +94 -0
  214. paper_xlsx-0.1.0/openpyxl/worksheet/picture.py +8 -0
  215. paper_xlsx-0.1.0/openpyxl/worksheet/print_settings.py +184 -0
  216. paper_xlsx-0.1.0/openpyxl/worksheet/properties.py +97 -0
  217. paper_xlsx-0.1.0/openpyxl/worksheet/protection.py +120 -0
  218. paper_xlsx-0.1.0/openpyxl/worksheet/related.py +17 -0
  219. paper_xlsx-0.1.0/openpyxl/worksheet/scenario.py +105 -0
  220. paper_xlsx-0.1.0/openpyxl/worksheet/smart_tag.py +78 -0
  221. paper_xlsx-0.1.0/openpyxl/worksheet/table.py +385 -0
  222. paper_xlsx-0.1.0/openpyxl/worksheet/views.py +155 -0
  223. paper_xlsx-0.1.0/openpyxl/worksheet/worksheet.py +1021 -0
  224. paper_xlsx-0.1.0/openpyxl/writer/__init__.py +1 -0
  225. paper_xlsx-0.1.0/openpyxl/writer/excel.py +330 -0
  226. paper_xlsx-0.1.0/openpyxl/writer/theme.py +291 -0
  227. paper_xlsx-0.1.0/openpyxl/xml/__init__.py +42 -0
  228. paper_xlsx-0.1.0/openpyxl/xml/constants.py +129 -0
  229. paper_xlsx-0.1.0/openpyxl/xml/functions.py +87 -0
  230. paper_xlsx-0.1.0/paper_xlsx.egg-info/PKG-INFO +190 -0
  231. paper_xlsx-0.1.0/paper_xlsx.egg-info/SOURCES.txt +236 -0
  232. paper_xlsx-0.1.0/paper_xlsx.egg-info/dependency_links.txt +1 -0
  233. paper_xlsx-0.1.0/paper_xlsx.egg-info/requires.txt +1 -0
  234. paper_xlsx-0.1.0/paper_xlsx.egg-info/top_level.txt +1 -0
  235. paper_xlsx-0.1.0/pyproject.toml +3 -0
  236. paper_xlsx-0.1.0/setup.cfg +10 -0
  237. paper_xlsx-0.1.0/setup.py +104 -0
@@ -0,0 +1,98 @@
1
+ This project was started by Eric Gazoni. In 2013 Charlie Clark became
2
+ co-maintainer of the project.
3
+
4
+ It was initially *heavily* inspired by the PHPExcel library:
5
+ http://www.phpexcel.net/
6
+
7
+ Thanks to all those who participate in the project (in alphabetical order):
8
+
9
+ * aceMueller
10
+ * Adam Lofts
11
+ * Adam Morris
12
+ * Alessandro Cucci
13
+ * Alex Gronholm
14
+ * Alexander Ley
15
+ * Alexandre Fayolle
16
+ * Amin Mirzaee
17
+ * Anders Chrigstrom
18
+ * Anthony Hayward
19
+ * Bernt R. Brenna
20
+ * Brent Hoover
21
+ * Brice Gelineau
22
+ * ccoacley
23
+ * Chi Ho Kwok
24
+ * Cory Kramer
25
+ * Day Barr
26
+ * Detlef Lannert
27
+ * Dieter Vandenbussche
28
+ * Dmitriy Chernyshov
29
+ * Dominik Geldmacher
30
+ * Don Freeman
31
+ * Eirikur Fannar Torfason
32
+ * Elias Rabel
33
+ * Eric Chlebek
34
+ * Eric Gazoni
35
+ * Eric Hurkman
36
+ * Etienne Desautels
37
+ * Felipe Ochoa
38
+ * Felix Siebeneicker
39
+ * Fumito Hamamura
40
+ * Gabi Nagy
41
+ * Gar Thompson
42
+ * Gerald Van Huffelen
43
+ * Greg Lehmann
44
+ * Heikki Junes
45
+ * Israel Barth Rubio
46
+ * Jacob Middag
47
+ * James Smagala
48
+ * JarekPS
49
+ * Jean Pierre Huart
50
+ * Jeff Holman
51
+ * John Woltman IV
52
+ * Jonathan Peirce
53
+ * Joseph Tate
54
+ * Josh Haywood
55
+ * Jun Omae
56
+ * Kay Webber
57
+ * Khchine Hamza
58
+ * Klaus Bremer
59
+ * Koert van der Veer
60
+ * Laurent Laporte
61
+ * Laurent Vasseur
62
+ * Liam Sanders
63
+ * Maarten De Paepe
64
+ * Magnus Schieder
65
+ * Mark Gemmill
66
+ * Marko Loparic
67
+ * Masato Yoshida
68
+ * Max Bolingbroke
69
+ * Nicholas Laver
70
+ * Nis Martensen
71
+ * Paul Joyce
72
+ * Paul Van Der Linden
73
+ * Philip Roche
74
+ * Primoz Godec
75
+ * ramn_se
76
+ * René Neumann
77
+ * Rick Rankin
78
+ * Samuel Loretan
79
+ * Sergey Pikhovkin
80
+ * Shekhar Gyanwali
81
+ * Shibukawa Yoshiki
82
+ * Stefan Behnel
83
+ * Stephane Bard
84
+ * Stephen Rauch
85
+ * Sven Burk
86
+ * Ted Pollari
87
+ * Thomas Nygards
88
+ * Victor Korobkovsky
89
+ * Waldemar Osuch
90
+ * Wojciech Rola
91
+ * Wolfgane Scherer
92
+ * Yaroslav Halchenko
93
+ * Yash Jhunjhunwala
94
+ * Yingjie Lan
95
+ * Leetao
96
+
97
+ Project logo designed by Eric Gazoni, font by claudeserieux
98
+ (http://www.dafont.com/profile.php?user=337503)
@@ -0,0 +1,24 @@
1
+ This software is under the MIT Licence
2
+ ======================================
3
+
4
+ Copyright (c) 2010 openpyxl
5
+ Portions Copyright (c) 2026 Paper Instruments, Inc.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a
8
+ copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included
16
+ in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ prune openpyxl/sample
2
+ prune openpyxl/benchmarks
3
+ prune openpyxl/develop
4
+ prune scratchpad
5
+ prune doc
6
+
7
+ include *.rst
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.4
2
+ Name: paper-xlsx
3
+ Version: 0.1.0
4
+ Summary: A Python library to read/write Excel 2010 xlsx/xlsm files
5
+ Home-page: https://github.com/The-LLM-Data-Company/paper-xlsx
6
+ Author: See AUTHORS; Paper Instruments, Inc.
7
+ Author-email: charlie.clark@clark-consulting.eu
8
+ Maintainer: Paper Instruments, Inc.
9
+ License: MIT
10
+ Project-URL: Documentation, https://openpyxl.readthedocs.io/en/stable/
11
+ Project-URL: Source, https://github.com/The-LLM-Data-Company/paper-xlsx
12
+ Project-URL: Tracker, https://github.com/The-LLM-Data-Company/paper-xlsx/issues
13
+ Project-URL: Upstream, https://foss.heptapod.net/openpyxl/openpyxl
14
+ Classifier: Development Status :: 5 - Production/Stable
15
+ Classifier: Operating System :: MacOS :: MacOS X
16
+ Classifier: Operating System :: Microsoft :: Windows
17
+ Classifier: Operating System :: POSIX
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python
20
+ Classifier: Programming Language :: Python :: 3.6
21
+ Classifier: Programming Language :: Python :: 3.7
22
+ Classifier: Programming Language :: Python :: 3.8
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Requires-Python: >=3.8
27
+ License-File: LICENCE.rst
28
+ Requires-Dist: et_xmlfile
29
+ Dynamic: author
30
+ Dynamic: author-email
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: home-page
34
+ Dynamic: license
35
+ Dynamic: license-file
36
+ Dynamic: maintainer
37
+ Dynamic: project-url
38
+ Dynamic: requires-dist
39
+ Dynamic: requires-python
40
+ Dynamic: summary
41
+
42
+ paper-xlsx
43
+ ==========
44
+
45
+ ``paper-xlsx`` is an agent-first Python library for safely inspecting and
46
+ editing existing Excel (``.xlsx``) files. It is a strict-superset hard fork of
47
+ ``openpyxl`` 3.1.5 and a drop-in replacement. The distribution is renamed; the
48
+ import name stays ``openpyxl``, so existing code keeps working unchanged.
49
+
50
+ Why it exists
51
+ -------------
52
+
53
+ openpyxl is excellent at *creating* a workbook from scratch. The harder problem
54
+ is changing a real workbook without dropping charts or leaving formulas pointed
55
+ at the wrong cells. That is **silent corruption**: a file that opens fine and is
56
+ quietly wrong, often with numbers that still look plausible.
57
+
58
+ An agent cannot eyeball the result. It needs the workbook's structure and every
59
+ edit outcome as typed, machine-readable data, and it needs the library to refuse
60
+ rather than guess.
61
+
62
+ Safety contract
63
+ ---------------
64
+
65
+ Preserve mode applies the shared rule: every operation either does exactly what
66
+ it claims or refuses atomically. ``load_workbook(path, preserve=True)`` keeps the
67
+ original package bytes as the source of truth. Every session has one of three
68
+ explicit outcomes:
69
+
70
+ * a **correct save**: your edits are spliced into the original bytes, and
71
+ everything untouched survives byte-identical;
72
+ * a **typed refusal**: an unsafe edit changes nothing on disk or in memory and
73
+ the exception names the remedy;
74
+ * a **loud warning**: a stock-mode path reports that an operation may be lossy.
75
+
76
+ ``manifest``, ``model_map``, and ``locate`` expose workbook structure. Six
77
+ pinned JSON schemas make their results available as structured data.
78
+
79
+ Quick start
80
+ -----------
81
+
82
+ .. code-block:: python
83
+
84
+ from openpyxl import Workbook, load_workbook
85
+
86
+ # create a workbook with an input and a formula
87
+ wb = Workbook()
88
+ ws = wb.active
89
+ ws["A1"], ws["B1"] = "Growth rate", 0.05
90
+ ws["A2"], ws["B2"] = "Revenue", 1000
91
+ ws["B3"] = "=B2 * (1 + B1)"
92
+ wb.save("model.xlsx")
93
+
94
+ # reopen it in preserve mode: the original bytes are the source of truth
95
+ wb = load_workbook("model.xlsx", preserve=True)
96
+
97
+ wb.manifest().to_dict() # what's in the file, what survives a save
98
+ wb.model_map().to_dict() # inputs / calculations / outputs
99
+ wb.active.locate("Growth rate") # find a value cell by its label
100
+
101
+ wb.set_input("Growth rate", 0.07) # set an input; does not overwrite formulas
102
+ receipt = wb.save("model_v2.xlsx", receipt=True)
103
+ receipt.to_dict()["cells_changed"] # {'xl/worksheets/sheet1.xml': {'B1': 'changed'}}
104
+
105
+ Structural edits follow the same contract. ``ws.insert_rows(5)`` rewrites the
106
+ formulas, defined names, and chart series that point into the shifted range and
107
+ returns an ``AddressRemap``. If it cannot rewrite a reference safely, it refuses
108
+ and lists every reference that would have broken.
109
+
110
+ Computing values
111
+ ----------------
112
+
113
+ ``paper-xlsx`` does not implement formula calculation. When LibreOffice is
114
+ installed, the library delegates calculation to it as the oracle:
115
+
116
+ .. code-block:: python
117
+
118
+ import openpyxl.oracle as oracle
119
+
120
+ ev = wb.evaluate(set={"Sheet!B1": 0.10}, read=["Sheet!B3"])
121
+ ev.outputs # {'Sheet!B3': 1100}
122
+ ev.certification.status # did LibreOffice reproduce the file's caches?
123
+ oracle.write_back("model.xlsx") # write cached values after certification
124
+
125
+ Six pinned JSON schemas (``workbook_manifest``, ``model_map``, ``evaluation``,
126
+ ``oracle_write_back``, ``edit_receipt``, ``workbook_diff``) make every result
127
+ machine-consumable. The **Preserve mode** guide (``doc/paper.rst``) provides the
128
+ complete API overview and refusal taxonomy.
129
+
130
+ Preserve mode is opt-in today: pass ``preserve=True`` per call, or set
131
+ ``PAPER_PRESERVE_DEFAULT=1``. Preserve-by-default for the public/pandas API
132
+ is release-gated.
133
+
134
+ Drop-in and name map
135
+ --------------------
136
+
137
+ Only the distribution and repository are renamed. The importable package stays
138
+ ``openpyxl``. This is the same distribution/import split as Pillow
139
+ (``pip install pillow``, ``import PIL``), and it preserves existing code,
140
+ snippets, and model priors. Existing code that says ``import openpyxl`` keeps
141
+ working unchanged, and every upstream feature is still available. Preserve mode
142
+ and the new API are purely additive.
143
+
144
+ * GitHub repository: ``paper-xlsx``
145
+ * PyPI distribution: ``paper-xlsx``
146
+ * Built wheel/sdist names: ``paper_xlsx-*``
147
+ * Python import: ``openpyxl``
148
+ * Fork sentinel: ``openpyxl.__paper_version__ = "0.1.0"``
149
+ * Upstream base: openpyxl **3.1.5** (marker tag ``paper-base``)
150
+
151
+ Upstream releases are merged (never rebased) on a roughly quarterly cadence, so
152
+ drop-in compatibility with openpyxl holds over time.
153
+
154
+ Installation
155
+ ------------
156
+
157
+ This repository is private for now and publication to PyPI is gated. Install
158
+ from Git::
159
+
160
+ pip install "paper-xlsx @ git+https://github.com/The-LLM-Data-Company/paper-xlsx.git@main"
161
+
162
+ Verification
163
+ ------------
164
+
165
+ ::
166
+
167
+ python -c "import openpyxl; print(openpyxl.__paper_version__)"
168
+
169
+ Expected output::
170
+
171
+ 0.1.0
172
+
173
+ How it's tested
174
+ ---------------
175
+
176
+ * Upstream openpyxl's test suite runs on every change to check compatibility
177
+ with existing behavior.
178
+ * A frozen, hash-pinned fixture corpus under ``tests/paper`` includes real
179
+ third-party files with provenance labels, rather than only self-generated
180
+ fixtures.
181
+ * The contract harness saves and reopens before asserting, enforces an exact
182
+ changed-part budget and refusal atomicity, and runs a headless LibreOffice
183
+ load smoke.
184
+
185
+ License
186
+ -------
187
+
188
+ MIT, inherited from openpyxl. Original work © the openpyxl authors; fork
189
+ additions © Paper Instruments, Inc. The fork preserves the upstream license and
190
+ attribution. See ``LICENCE.rst``.
@@ -0,0 +1,149 @@
1
+ paper-xlsx
2
+ ==========
3
+
4
+ ``paper-xlsx`` is an agent-first Python library for safely inspecting and
5
+ editing existing Excel (``.xlsx``) files. It is a strict-superset hard fork of
6
+ ``openpyxl`` 3.1.5 and a drop-in replacement. The distribution is renamed; the
7
+ import name stays ``openpyxl``, so existing code keeps working unchanged.
8
+
9
+ Why it exists
10
+ -------------
11
+
12
+ openpyxl is excellent at *creating* a workbook from scratch. The harder problem
13
+ is changing a real workbook without dropping charts or leaving formulas pointed
14
+ at the wrong cells. That is **silent corruption**: a file that opens fine and is
15
+ quietly wrong, often with numbers that still look plausible.
16
+
17
+ An agent cannot eyeball the result. It needs the workbook's structure and every
18
+ edit outcome as typed, machine-readable data, and it needs the library to refuse
19
+ rather than guess.
20
+
21
+ Safety contract
22
+ ---------------
23
+
24
+ Preserve mode applies the shared rule: every operation either does exactly what
25
+ it claims or refuses atomically. ``load_workbook(path, preserve=True)`` keeps the
26
+ original package bytes as the source of truth. Every session has one of three
27
+ explicit outcomes:
28
+
29
+ * a **correct save**: your edits are spliced into the original bytes, and
30
+ everything untouched survives byte-identical;
31
+ * a **typed refusal**: an unsafe edit changes nothing on disk or in memory and
32
+ the exception names the remedy;
33
+ * a **loud warning**: a stock-mode path reports that an operation may be lossy.
34
+
35
+ ``manifest``, ``model_map``, and ``locate`` expose workbook structure. Six
36
+ pinned JSON schemas make their results available as structured data.
37
+
38
+ Quick start
39
+ -----------
40
+
41
+ .. code-block:: python
42
+
43
+ from openpyxl import Workbook, load_workbook
44
+
45
+ # create a workbook with an input and a formula
46
+ wb = Workbook()
47
+ ws = wb.active
48
+ ws["A1"], ws["B1"] = "Growth rate", 0.05
49
+ ws["A2"], ws["B2"] = "Revenue", 1000
50
+ ws["B3"] = "=B2 * (1 + B1)"
51
+ wb.save("model.xlsx")
52
+
53
+ # reopen it in preserve mode: the original bytes are the source of truth
54
+ wb = load_workbook("model.xlsx", preserve=True)
55
+
56
+ wb.manifest().to_dict() # what's in the file, what survives a save
57
+ wb.model_map().to_dict() # inputs / calculations / outputs
58
+ wb.active.locate("Growth rate") # find a value cell by its label
59
+
60
+ wb.set_input("Growth rate", 0.07) # set an input; does not overwrite formulas
61
+ receipt = wb.save("model_v2.xlsx", receipt=True)
62
+ receipt.to_dict()["cells_changed"] # {'xl/worksheets/sheet1.xml': {'B1': 'changed'}}
63
+
64
+ Structural edits follow the same contract. ``ws.insert_rows(5)`` rewrites the
65
+ formulas, defined names, and chart series that point into the shifted range and
66
+ returns an ``AddressRemap``. If it cannot rewrite a reference safely, it refuses
67
+ and lists every reference that would have broken.
68
+
69
+ Computing values
70
+ ----------------
71
+
72
+ ``paper-xlsx`` does not implement formula calculation. When LibreOffice is
73
+ installed, the library delegates calculation to it as the oracle:
74
+
75
+ .. code-block:: python
76
+
77
+ import openpyxl.oracle as oracle
78
+
79
+ ev = wb.evaluate(set={"Sheet!B1": 0.10}, read=["Sheet!B3"])
80
+ ev.outputs # {'Sheet!B3': 1100}
81
+ ev.certification.status # did LibreOffice reproduce the file's caches?
82
+ oracle.write_back("model.xlsx") # write cached values after certification
83
+
84
+ Six pinned JSON schemas (``workbook_manifest``, ``model_map``, ``evaluation``,
85
+ ``oracle_write_back``, ``edit_receipt``, ``workbook_diff``) make every result
86
+ machine-consumable. The **Preserve mode** guide (``doc/paper.rst``) provides the
87
+ complete API overview and refusal taxonomy.
88
+
89
+ Preserve mode is opt-in today: pass ``preserve=True`` per call, or set
90
+ ``PAPER_PRESERVE_DEFAULT=1``. Preserve-by-default for the public/pandas API
91
+ is release-gated.
92
+
93
+ Drop-in and name map
94
+ --------------------
95
+
96
+ Only the distribution and repository are renamed. The importable package stays
97
+ ``openpyxl``. This is the same distribution/import split as Pillow
98
+ (``pip install pillow``, ``import PIL``), and it preserves existing code,
99
+ snippets, and model priors. Existing code that says ``import openpyxl`` keeps
100
+ working unchanged, and every upstream feature is still available. Preserve mode
101
+ and the new API are purely additive.
102
+
103
+ * GitHub repository: ``paper-xlsx``
104
+ * PyPI distribution: ``paper-xlsx``
105
+ * Built wheel/sdist names: ``paper_xlsx-*``
106
+ * Python import: ``openpyxl``
107
+ * Fork sentinel: ``openpyxl.__paper_version__ = "0.1.0"``
108
+ * Upstream base: openpyxl **3.1.5** (marker tag ``paper-base``)
109
+
110
+ Upstream releases are merged (never rebased) on a roughly quarterly cadence, so
111
+ drop-in compatibility with openpyxl holds over time.
112
+
113
+ Installation
114
+ ------------
115
+
116
+ This repository is private for now and publication to PyPI is gated. Install
117
+ from Git::
118
+
119
+ pip install "paper-xlsx @ git+https://github.com/The-LLM-Data-Company/paper-xlsx.git@main"
120
+
121
+ Verification
122
+ ------------
123
+
124
+ ::
125
+
126
+ python -c "import openpyxl; print(openpyxl.__paper_version__)"
127
+
128
+ Expected output::
129
+
130
+ 0.1.0
131
+
132
+ How it's tested
133
+ ---------------
134
+
135
+ * Upstream openpyxl's test suite runs on every change to check compatibility
136
+ with existing behavior.
137
+ * A frozen, hash-pinned fixture corpus under ``tests/paper`` includes real
138
+ third-party files with provenance labels, rather than only self-generated
139
+ fixtures.
140
+ * The contract harness saves and reopens before asserting, enforces an exact
141
+ changed-part budget and refusal atomicity, and runs a headless LibreOffice
142
+ load smoke.
143
+
144
+ License
145
+ -------
146
+
147
+ MIT, inherited from openpyxl. Original work © the openpyxl authors; fork
148
+ additions © Paper Instruments, Inc. The fork preserves the upstream license and
149
+ attribution. See ``LICENCE.rst``.
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2010-2024 openpyxl
2
+
3
+ """paper-xlsx — Paper Instruments' hard fork of openpyxl for LOSSLESS,
4
+ SAFE editing of existing Excel files.
5
+
6
+ The import name stays ``openpyxl`` so existing code is unchanged. The
7
+ fork adds a **preserve mode**: ``load_workbook(path, preserve=True)``
8
+ keeps the original package bytes as the source of truth, so saving
9
+ splices your edits back in without destroying the charts, pivots, VBA,
10
+ or formatting a normal openpyxl round-trip drops — and any edit it
11
+ cannot make safely refuses loudly (a typed :mod:`openpyxl.errors`
12
+ exception) instead of corrupting the file.
13
+
14
+ Start here: :attr:`openpyxl.__paper_version__` (fork sentinel), and the
15
+ :mod:`openpyxl.preserve`, :mod:`openpyxl.oracle` and
16
+ :mod:`openpyxl.errors` modules. The project README and ``doc/paper.rst``
17
+ give the full tour.
18
+ """
19
+
20
+ DEBUG = False
21
+
22
+ from openpyxl.compat.numbers import NUMPY
23
+ from openpyxl.xml import DEFUSEDXML, LXML
24
+ from openpyxl.workbook import Workbook
25
+ from openpyxl.reader.excel import load_workbook as open
26
+ from openpyxl.reader.excel import load_workbook
27
+ import openpyxl._constants as constants
28
+
29
+ # Expose constants especially the version number
30
+
31
+ __author__ = constants.__author__
32
+ __author_email__ = constants.__author_email__
33
+ __license__ = constants.__license__
34
+ __maintainer_email__ = constants.__maintainer_email__
35
+ __url__ = constants.__url__
36
+ __version__ = constants.__version__
37
+ __paper_version__ = "0.1.0"
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2010-2024 openpyxl
2
+
3
+ """
4
+ Package metadata
5
+ """
6
+
7
+ __author__ = "See AUTHORS"
8
+ __author_email__ = "charlie.clark@clark-consulting.eu"
9
+ __license__ = "MIT"
10
+ __maintainer_email__ = "openpyxl-users@googlegroups.com"
11
+ __url__ = "https://github.com/The-LLM-Data-Company/paper-xlsx"
12
+ __version__ = "3.1.5"
13
+ __python__ = "3.8"
@@ -0,0 +1,4 @@
1
+ # Copyright (c) 2010-2024 openpyxl
2
+
3
+ from .cell import Cell, WriteOnlyCell, MergedCell
4
+ from .read_only import ReadOnlyCell
@@ -0,0 +1,136 @@
1
+ # Copyright (c) 2010-2024 openpyxl
2
+
3
+ from openpyxl.compat import safe_string
4
+ from openpyxl.xml.functions import Element, SubElement, whitespace, XML_NS
5
+ from openpyxl import LXML
6
+ from openpyxl.utils.datetime import to_excel, to_ISO8601
7
+ from datetime import timedelta
8
+
9
+ from openpyxl.worksheet.formula import DataTableFormula, ArrayFormula
10
+ from openpyxl.cell.rich_text import CellRichText
11
+
12
+ def _set_attributes(cell, styled=None):
13
+ """
14
+ Set coordinate and datatype
15
+ """
16
+ coordinate = cell.coordinate
17
+ attrs = {'r': coordinate}
18
+ if styled:
19
+ attrs['s'] = f"{cell.style_id}"
20
+
21
+ if cell.data_type == "s":
22
+ attrs['t'] = "inlineStr"
23
+ elif cell.data_type != 'f':
24
+ attrs['t'] = cell.data_type
25
+
26
+ value = cell._value
27
+
28
+ if cell.data_type == "d":
29
+ if hasattr(value, "tzinfo") and value.tzinfo is not None:
30
+ raise TypeError("Excel does not support timezones in datetimes. "
31
+ "The tzinfo in the datetime/time object must be set to None.")
32
+
33
+ if cell.parent.parent.iso_dates and not isinstance(value, timedelta):
34
+ value = to_ISO8601(value)
35
+ else:
36
+ attrs['t'] = "n"
37
+ value = to_excel(value, cell.parent.parent.epoch)
38
+
39
+ if cell.hyperlink:
40
+ cell.parent._hyperlinks.append(cell.hyperlink)
41
+
42
+ return value, attrs
43
+
44
+
45
+ def etree_write_cell(xf, worksheet, cell, styled=None):
46
+
47
+ value, attributes = _set_attributes(cell, styled)
48
+
49
+ el = Element("c", attributes)
50
+ if value is None or value == "":
51
+ xf.write(el)
52
+ return
53
+
54
+ if cell.data_type == 'f':
55
+ attrib = {}
56
+
57
+ if isinstance(value, ArrayFormula):
58
+ attrib = dict(value)
59
+ value = value.text
60
+
61
+ elif isinstance(value, DataTableFormula):
62
+ attrib = dict(value)
63
+ value = None
64
+
65
+ formula = SubElement(el, 'f', attrib)
66
+ if value is not None and not attrib.get('t') == "dataTable":
67
+ formula.text = value[1:]
68
+ value = None
69
+
70
+ if cell.data_type == 's':
71
+ if isinstance(value, CellRichText):
72
+ el.append(value.to_tree())
73
+ else:
74
+ inline_string = Element("is")
75
+ text = Element('t')
76
+ text.text = value
77
+ whitespace(text)
78
+ inline_string.append(text)
79
+ el.append(inline_string)
80
+
81
+ else:
82
+ cell_content = SubElement(el, 'v')
83
+ if value is not None:
84
+ cell_content.text = safe_string(value)
85
+
86
+ xf.write(el)
87
+
88
+
89
+ def lxml_write_cell(xf, worksheet, cell, styled=False):
90
+ value, attributes = _set_attributes(cell, styled)
91
+
92
+ if value == '' or value is None:
93
+ with xf.element("c", attributes):
94
+ return
95
+
96
+ with xf.element('c', attributes):
97
+ if cell.data_type == 'f':
98
+ attrib = {}
99
+
100
+ if isinstance(value, ArrayFormula):
101
+ attrib = dict(value)
102
+ value = value.text
103
+
104
+ elif isinstance(value, DataTableFormula):
105
+ attrib = dict(value)
106
+ value = None
107
+
108
+ with xf.element('f', attrib):
109
+ if value is not None and not attrib.get('t') == "dataTable":
110
+ xf.write(value[1:])
111
+ value = None
112
+
113
+ if cell.data_type == 's':
114
+ if isinstance(value, CellRichText):
115
+ el = value.to_tree()
116
+ xf.write(el)
117
+ else:
118
+ with xf.element("is"):
119
+ if isinstance(value, str):
120
+ attrs = {}
121
+ if value != value.strip():
122
+ attrs["{%s}space" % XML_NS] = "preserve"
123
+ el = Element("t", attrs) # lxml can't handle xml-ns
124
+ el.text = value
125
+ xf.write(el)
126
+
127
+ else:
128
+ with xf.element("v"):
129
+ if value is not None:
130
+ xf.write(safe_string(value))
131
+
132
+
133
+ if LXML:
134
+ write_cell = lxml_write_cell
135
+ else:
136
+ write_cell = etree_write_cell