aspose-cells-foss 25.12.1__py3-none-any.whl → 26.2.2__py3-none-any.whl

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 (93) hide show
  1. aspose_cells/__init__.py +88 -0
  2. aspose_cells/auto_filter.py +527 -0
  3. aspose_cells/cell.py +483 -0
  4. aspose_cells/cell_value_handler.py +319 -0
  5. aspose_cells/cells.py +779 -0
  6. aspose_cells/cfb_handler.py +445 -0
  7. aspose_cells/cfb_writer.py +659 -0
  8. aspose_cells/cfb_writer_minimal.py +337 -0
  9. aspose_cells/comment_xml.py +475 -0
  10. aspose_cells/conditional_format.py +1185 -0
  11. aspose_cells/csv_handler.py +690 -0
  12. aspose_cells/data_validation.py +911 -0
  13. aspose_cells/document_properties.py +356 -0
  14. aspose_cells/encryption_crypto.py +247 -0
  15. aspose_cells/encryption_params.py +138 -0
  16. aspose_cells/hyperlink.py +372 -0
  17. aspose_cells/json_handler.py +185 -0
  18. aspose_cells/markdown_handler.py +583 -0
  19. aspose_cells/shared_strings.py +101 -0
  20. aspose_cells/style.py +841 -0
  21. aspose_cells/workbook.py +499 -0
  22. aspose_cells/workbook_hash_password.py +68 -0
  23. aspose_cells/workbook_properties.py +712 -0
  24. aspose_cells/worksheet.py +570 -0
  25. aspose_cells/worksheet_properties.py +1239 -0
  26. aspose_cells/xlsx_encryptor.py +403 -0
  27. aspose_cells/xml_autofilter_loader.py +195 -0
  28. aspose_cells/xml_autofilter_saver.py +173 -0
  29. aspose_cells/xml_conditional_format_loader.py +215 -0
  30. aspose_cells/xml_conditional_format_saver.py +351 -0
  31. aspose_cells/xml_datavalidation_loader.py +239 -0
  32. aspose_cells/xml_datavalidation_saver.py +245 -0
  33. aspose_cells/xml_hyperlink_handler.py +323 -0
  34. aspose_cells/xml_loader.py +986 -0
  35. aspose_cells/xml_properties_loader.py +512 -0
  36. aspose_cells/xml_properties_saver.py +607 -0
  37. aspose_cells/xml_saver.py +1306 -0
  38. aspose_cells_foss-26.2.2.dist-info/METADATA +190 -0
  39. aspose_cells_foss-26.2.2.dist-info/RECORD +41 -0
  40. {aspose_cells_foss-25.12.1.dist-info → aspose_cells_foss-26.2.2.dist-info}/WHEEL +1 -1
  41. aspose_cells_foss-26.2.2.dist-info/top_level.txt +1 -0
  42. aspose/__init__.py +0 -14
  43. aspose/cells/__init__.py +0 -31
  44. aspose/cells/cell.py +0 -350
  45. aspose/cells/constants.py +0 -44
  46. aspose/cells/converters/__init__.py +0 -13
  47. aspose/cells/converters/csv_converter.py +0 -55
  48. aspose/cells/converters/json_converter.py +0 -46
  49. aspose/cells/converters/markdown_converter.py +0 -453
  50. aspose/cells/drawing/__init__.py +0 -17
  51. aspose/cells/drawing/anchor.py +0 -172
  52. aspose/cells/drawing/collection.py +0 -233
  53. aspose/cells/drawing/image.py +0 -338
  54. aspose/cells/formats.py +0 -80
  55. aspose/cells/formula/__init__.py +0 -10
  56. aspose/cells/formula/evaluator.py +0 -360
  57. aspose/cells/formula/functions.py +0 -433
  58. aspose/cells/formula/tokenizer.py +0 -340
  59. aspose/cells/io/__init__.py +0 -27
  60. aspose/cells/io/csv/__init__.py +0 -8
  61. aspose/cells/io/csv/reader.py +0 -88
  62. aspose/cells/io/csv/writer.py +0 -98
  63. aspose/cells/io/factory.py +0 -138
  64. aspose/cells/io/interfaces.py +0 -48
  65. aspose/cells/io/json/__init__.py +0 -8
  66. aspose/cells/io/json/reader.py +0 -126
  67. aspose/cells/io/json/writer.py +0 -119
  68. aspose/cells/io/md/__init__.py +0 -8
  69. aspose/cells/io/md/reader.py +0 -161
  70. aspose/cells/io/md/writer.py +0 -334
  71. aspose/cells/io/models.py +0 -64
  72. aspose/cells/io/xlsx/__init__.py +0 -9
  73. aspose/cells/io/xlsx/constants.py +0 -312
  74. aspose/cells/io/xlsx/image_writer.py +0 -311
  75. aspose/cells/io/xlsx/reader.py +0 -284
  76. aspose/cells/io/xlsx/writer.py +0 -931
  77. aspose/cells/plugins/__init__.py +0 -6
  78. aspose/cells/plugins/docling_backend/__init__.py +0 -7
  79. aspose/cells/plugins/docling_backend/backend.py +0 -535
  80. aspose/cells/plugins/markitdown_plugin/__init__.py +0 -15
  81. aspose/cells/plugins/markitdown_plugin/plugin.py +0 -128
  82. aspose/cells/range.py +0 -210
  83. aspose/cells/style.py +0 -287
  84. aspose/cells/utils/__init__.py +0 -54
  85. aspose/cells/utils/coordinates.py +0 -68
  86. aspose/cells/utils/exceptions.py +0 -43
  87. aspose/cells/utils/validation.py +0 -102
  88. aspose/cells/workbook.py +0 -352
  89. aspose/cells/worksheet.py +0 -670
  90. aspose_cells_foss-25.12.1.dist-info/METADATA +0 -189
  91. aspose_cells_foss-25.12.1.dist-info/RECORD +0 -53
  92. aspose_cells_foss-25.12.1.dist-info/entry_points.txt +0 -2
  93. aspose_cells_foss-25.12.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,1239 @@
1
+ """
2
+ Aspose.Cells for Python - Worksheet Properties Module
3
+
4
+ This module provides classes for worksheet-level properties according to ECMA-376 specification.
5
+ Includes sheet views, sheet format, sheet protection, page setup, page margins, and header/footer.
6
+
7
+ ECMA-376 Sections: 18.3.1
8
+ """
9
+
10
+
11
+ class SheetView:
12
+ """
13
+ Represents a sheet view configuration.
14
+
15
+ ECMA-376 Section: 18.3.1.87
16
+
17
+ Examples:
18
+ >>> ws.properties.view.show_grid_lines = False
19
+ >>> ws.properties.view.zoom_scale = 80
20
+ """
21
+
22
+ def __init__(self):
23
+ self._window_protection = False
24
+ self._show_formulas = False
25
+ self._show_grid_lines = True
26
+ self._show_row_col_headers = True
27
+ self._show_outline_symbols = True
28
+ self._show_zeros = True
29
+ self._right_to_left = False
30
+ self._tab_selected = False
31
+ self._show_ruler = True
32
+ self._show_white_space = True
33
+ self._view = 'normal'
34
+ self._top_left_cell = None
35
+ self._default_grid_color = True
36
+ self._color_id = None
37
+ self._zoom_scale = 100
38
+ self._zoom_scale_normal = 0
39
+ self._zoom_scale_page_layout_view = 0
40
+ self._zoom_scale_sheet_layout_view = 0
41
+ self._workbook_view_id = 0
42
+
43
+ @property
44
+ def show_formulas(self):
45
+ """Whether to show formulas instead of values."""
46
+ return self._show_formulas
47
+
48
+ @show_formulas.setter
49
+ def show_formulas(self, value):
50
+ self._show_formulas = value
51
+
52
+ @property
53
+ def show_grid_lines(self):
54
+ """Whether to show grid lines."""
55
+ return self._show_grid_lines
56
+
57
+ @show_grid_lines.setter
58
+ def show_grid_lines(self, value):
59
+ self._show_grid_lines = value
60
+
61
+ @property
62
+ def show_row_col_headers(self):
63
+ """Whether to show row and column headers."""
64
+ return self._show_row_col_headers
65
+
66
+ @show_row_col_headers.setter
67
+ def show_row_col_headers(self, value):
68
+ self._show_row_col_headers = value
69
+
70
+ @property
71
+ def show_zeros(self):
72
+ """Whether to display zero values."""
73
+ return self._show_zeros
74
+
75
+ @show_zeros.setter
76
+ def show_zeros(self, value):
77
+ self._show_zeros = value
78
+
79
+ @property
80
+ def right_to_left(self):
81
+ """Whether to display right-to-left."""
82
+ return self._right_to_left
83
+
84
+ @right_to_left.setter
85
+ def right_to_left(self, value):
86
+ self._right_to_left = value
87
+
88
+ @property
89
+ def tab_selected(self):
90
+ """Whether this sheet is selected."""
91
+ return self._tab_selected
92
+
93
+ @tab_selected.setter
94
+ def tab_selected(self, value):
95
+ self._tab_selected = value
96
+
97
+ @property
98
+ def view(self):
99
+ """View mode: 'normal', 'pageBreakPreview', or 'pageLayout'."""
100
+ return self._view
101
+
102
+ @view.setter
103
+ def view(self, value):
104
+ if value not in ('normal', 'pageBreakPreview', 'pageLayout'):
105
+ raise ValueError("view must be 'normal', 'pageBreakPreview', or 'pageLayout'")
106
+ self._view = value
107
+
108
+ @property
109
+ def top_left_cell(self):
110
+ """Top-left visible cell."""
111
+ return self._top_left_cell
112
+
113
+ @top_left_cell.setter
114
+ def top_left_cell(self, value):
115
+ self._top_left_cell = value
116
+
117
+ @property
118
+ def zoom_scale(self):
119
+ """Zoom scale (10-400, default: 100)."""
120
+ return self._zoom_scale
121
+
122
+ @zoom_scale.setter
123
+ def zoom_scale(self, value):
124
+ if value < 10 or value > 400:
125
+ raise ValueError("zoom_scale must be between 10 and 400")
126
+ self._zoom_scale = value
127
+
128
+ @property
129
+ def zoom_scale_normal(self):
130
+ """Normal zoom scale."""
131
+ return self._zoom_scale_normal
132
+
133
+ @zoom_scale_normal.setter
134
+ def zoom_scale_normal(self, value):
135
+ self._zoom_scale_normal = value
136
+
137
+ @property
138
+ def zoom_scale_page_layout_view(self):
139
+ """Zoom for page layout view."""
140
+ return self._zoom_scale_page_layout_view
141
+
142
+ @zoom_scale_page_layout_view.setter
143
+ def zoom_scale_page_layout_view(self, value):
144
+ self._zoom_scale_page_layout_view = value
145
+
146
+ @property
147
+ def view_type(self):
148
+ """Alias for view property. View mode: 'normal', 'pageBreakPreview', or 'pageLayout'."""
149
+ return self._view
150
+
151
+ @view_type.setter
152
+ def view_type(self, value):
153
+ if value not in ('normal', 'pageBreakPreview', 'pageLayout'):
154
+ raise ValueError("view_type must be 'normal', 'pageBreakPreview', or 'pageLayout'")
155
+ self._view = value
156
+
157
+ @property
158
+ def window_protection(self):
159
+ """Whether the sheet window is protected."""
160
+ return self._window_protection
161
+
162
+ @window_protection.setter
163
+ def window_protection(self, value):
164
+ self._window_protection = value
165
+
166
+ @property
167
+ def show_outline_symbols(self):
168
+ """Whether to show outline symbols."""
169
+ return self._show_outline_symbols
170
+
171
+ @show_outline_symbols.setter
172
+ def show_outline_symbols(self, value):
173
+ self._show_outline_symbols = value
174
+
175
+ @property
176
+ def show_ruler(self):
177
+ """Whether to show the ruler."""
178
+ return self._show_ruler
179
+
180
+ @show_ruler.setter
181
+ def show_ruler(self, value):
182
+ self._show_ruler = value
183
+
184
+ @property
185
+ def show_white_space(self):
186
+ """Whether to show white space."""
187
+ return self._show_white_space
188
+
189
+ @show_white_space.setter
190
+ def show_white_space(self, value):
191
+ self._show_white_space = value
192
+
193
+ @property
194
+ def default_grid_color(self):
195
+ """Whether to use the default grid color."""
196
+ return self._default_grid_color
197
+
198
+ @default_grid_color.setter
199
+ def default_grid_color(self, value):
200
+ self._default_grid_color = value
201
+
202
+ @property
203
+ def color_id(self):
204
+ """Grid color index (default 64)."""
205
+ return self._color_id
206
+
207
+ @color_id.setter
208
+ def color_id(self, value):
209
+ self._color_id = value
210
+
211
+ @property
212
+ def zoom_scale_sheet_layout_view(self):
213
+ """Zoom for sheet layout view."""
214
+ return self._zoom_scale_sheet_layout_view
215
+
216
+ @zoom_scale_sheet_layout_view.setter
217
+ def zoom_scale_sheet_layout_view(self, value):
218
+ self._zoom_scale_sheet_layout_view = value
219
+
220
+ @property
221
+ def workbook_view_id(self):
222
+ """Workbook view index for this sheet view."""
223
+ return self._workbook_view_id
224
+
225
+ @workbook_view_id.setter
226
+ def workbook_view_id(self, value):
227
+ self._workbook_view_id = value
228
+
229
+
230
+ class Selection:
231
+ """
232
+ Represents cell selection in a sheet view.
233
+
234
+ ECMA-376 Section: 18.3.1.81
235
+
236
+ Examples:
237
+ >>> ws.properties.selection.active_cell = "B2"
238
+ >>> ws.properties.selection.sqref = "B2:D5"
239
+ """
240
+
241
+ def __init__(self):
242
+ self._pane = None
243
+ self._active_cell = 'A1'
244
+ self._sqref = 'A1'
245
+ self._active_cell_id = 0
246
+
247
+ @property
248
+ def pane(self):
249
+ """Pane selection is in: 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'."""
250
+ return self._pane
251
+
252
+ @pane.setter
253
+ def pane(self, value):
254
+ self._pane = value
255
+
256
+ @property
257
+ def active_cell(self):
258
+ """Active cell reference."""
259
+ return self._active_cell
260
+
261
+ @active_cell.setter
262
+ def active_cell(self, value):
263
+ self._active_cell = value
264
+
265
+ @property
266
+ def sqref(self):
267
+ """Selected range (space-delimited for multiple ranges)."""
268
+ return self._sqref
269
+
270
+ @sqref.setter
271
+ def sqref(self, value):
272
+ self._sqref = value
273
+
274
+
275
+ class Pane:
276
+ """
277
+ Represents pane (freeze/split) settings.
278
+
279
+ ECMA-376 Section: 18.3.1.66
280
+
281
+ Examples:
282
+ >>> ws.properties.pane.x_split = 1
283
+ >>> ws.properties.pane.y_split = 1
284
+ >>> ws.properties.pane.state = "frozen"
285
+ """
286
+
287
+ def __init__(self):
288
+ self._x_split = None
289
+ self._y_split = None
290
+ self._top_left_cell = None
291
+ self._active_pane = None
292
+ self._state = None
293
+
294
+ @property
295
+ def x_split(self):
296
+ """Horizontal split position (column count or pixel position)."""
297
+ return self._x_split
298
+
299
+ @x_split.setter
300
+ def x_split(self, value):
301
+ self._x_split = value
302
+
303
+ @property
304
+ def y_split(self):
305
+ """Vertical split position (row count or pixel position)."""
306
+ return self._y_split
307
+
308
+ @y_split.setter
309
+ def y_split(self, value):
310
+ self._y_split = value
311
+
312
+ @property
313
+ def top_left_cell(self):
314
+ """Top-left cell of bottom-right pane."""
315
+ return self._top_left_cell
316
+
317
+ @top_left_cell.setter
318
+ def top_left_cell(self, value):
319
+ self._top_left_cell = value
320
+
321
+ @property
322
+ def active_pane(self):
323
+ """Active pane: 'bottomLeft', 'bottomRight', 'topLeft', 'topRight'."""
324
+ return self._active_pane
325
+
326
+ @active_pane.setter
327
+ def active_pane(self, value):
328
+ self._active_pane = value
329
+
330
+ @property
331
+ def state(self):
332
+ """Pane state: 'frozen', 'frozenSplit', or 'split'."""
333
+ return self._state
334
+
335
+ @state.setter
336
+ def state(self, value):
337
+ if value is not None and value not in ('frozen', 'frozenSplit', 'split'):
338
+ raise ValueError("state must be 'frozen', 'frozenSplit', or 'split'")
339
+ self._state = value
340
+
341
+ @property
342
+ def is_frozen(self):
343
+ """Returns True if pane is frozen."""
344
+ return self._state in ('frozen', 'frozenSplit')
345
+
346
+
347
+ class SheetFormatProperties:
348
+ """
349
+ Represents sheet format properties.
350
+
351
+ ECMA-376 Section: 18.3.1.82
352
+
353
+ Examples:
354
+ >>> ws.properties.format.default_row_height = 15
355
+ >>> ws.properties.format.default_col_width = 8.43
356
+ """
357
+
358
+ def __init__(self):
359
+ self._base_col_width = 8
360
+ self._default_col_width = None
361
+ self._default_row_height = 15.0
362
+ self._custom_height = False
363
+ self._zero_height = False
364
+ self._thick_top = False
365
+ self._thick_bottom = False
366
+ self._outline_level_row = 0
367
+ self._outline_level_col = 0
368
+
369
+ @property
370
+ def base_col_width(self):
371
+ """Base column width in characters (default: 8)."""
372
+ return self._base_col_width
373
+
374
+ @base_col_width.setter
375
+ def base_col_width(self, value):
376
+ self._base_col_width = value
377
+
378
+ @property
379
+ def default_col_width(self):
380
+ """Default column width in characters."""
381
+ return self._default_col_width
382
+
383
+ @default_col_width.setter
384
+ def default_col_width(self, value):
385
+ self._default_col_width = value
386
+
387
+ @property
388
+ def default_row_height(self):
389
+ """Default row height in points."""
390
+ return self._default_row_height
391
+
392
+ @default_row_height.setter
393
+ def default_row_height(self, value):
394
+ self._default_row_height = value
395
+
396
+ @property
397
+ def custom_height(self):
398
+ """Whether custom row height is applied."""
399
+ return self._custom_height
400
+
401
+ @custom_height.setter
402
+ def custom_height(self, value):
403
+ self._custom_height = value
404
+
405
+ @property
406
+ def zero_height(self):
407
+ """Whether rows have zero height by default."""
408
+ return self._zero_height
409
+
410
+ @zero_height.setter
411
+ def zero_height(self, value):
412
+ self._zero_height = value
413
+
414
+ @property
415
+ def outline_level_row(self):
416
+ """Default outline level for rows."""
417
+ return self._outline_level_row
418
+
419
+ @outline_level_row.setter
420
+ def outline_level_row(self, value):
421
+ self._outline_level_row = value
422
+
423
+ @property
424
+ def outline_level_col(self):
425
+ """Default outline level for columns."""
426
+ return self._outline_level_col
427
+
428
+ @outline_level_col.setter
429
+ def outline_level_col(self, value):
430
+ self._outline_level_col = value
431
+
432
+ @property
433
+ def thick_top(self):
434
+ """Whether thick top border is applied."""
435
+ return self._thick_top
436
+
437
+ @thick_top.setter
438
+ def thick_top(self, value):
439
+ self._thick_top = value
440
+
441
+ @property
442
+ def thick_bottom(self):
443
+ """Whether thick bottom border is applied."""
444
+ return self._thick_bottom
445
+
446
+ @thick_bottom.setter
447
+ def thick_bottom(self, value):
448
+ self._thick_bottom = value
449
+
450
+
451
+ class SheetProtection:
452
+ """
453
+ Represents sheet protection settings.
454
+
455
+ ECMA-376 Section: 18.3.1.85
456
+
457
+ Examples:
458
+ >>> ws.properties.protection.sheet = True
459
+ >>> ws.properties.protection.format_cells = False
460
+ """
461
+
462
+ def __init__(self):
463
+ self._algorithm_name = None
464
+ self._hash_value = None
465
+ self._salt_value = None
466
+ self._spin_count = None
467
+ self._sheet = False
468
+ self._objects = False
469
+ self._scenarios = False
470
+ self._format_cells = True
471
+ self._format_columns = True
472
+ self._format_rows = True
473
+ self._insert_columns = True
474
+ self._insert_rows = True
475
+ self._insert_hyperlinks = True
476
+ self._delete_columns = True
477
+ self._delete_rows = True
478
+ self._select_locked_cells = False
479
+ self._sort = True
480
+ self._auto_filter = True
481
+ self._pivot_tables = True
482
+ self._select_unlocked_cells = False
483
+ self._password = None
484
+
485
+ @property
486
+ def sheet(self):
487
+ """Whether to protect sheet."""
488
+ return self._sheet
489
+
490
+ @sheet.setter
491
+ def sheet(self, value):
492
+ self._sheet = value
493
+
494
+ @property
495
+ def objects(self):
496
+ """Whether to protect objects."""
497
+ return self._objects
498
+
499
+ @objects.setter
500
+ def objects(self, value):
501
+ self._objects = value
502
+
503
+ @property
504
+ def scenarios(self):
505
+ """Whether to protect scenarios."""
506
+ return self._scenarios
507
+
508
+ @scenarios.setter
509
+ def scenarios(self, value):
510
+ self._scenarios = value
511
+
512
+ @property
513
+ def format_cells(self):
514
+ """Whether to allow formatting cells."""
515
+ return self._format_cells
516
+
517
+ @format_cells.setter
518
+ def format_cells(self, value):
519
+ self._format_cells = value
520
+
521
+ @property
522
+ def format_columns(self):
523
+ """Whether to allow formatting columns."""
524
+ return self._format_columns
525
+
526
+ @format_columns.setter
527
+ def format_columns(self, value):
528
+ self._format_columns = value
529
+
530
+ @property
531
+ def format_rows(self):
532
+ """Whether to allow formatting rows."""
533
+ return self._format_rows
534
+
535
+ @format_rows.setter
536
+ def format_rows(self, value):
537
+ self._format_rows = value
538
+
539
+ @property
540
+ def insert_columns(self):
541
+ """Whether to allow inserting columns."""
542
+ return self._insert_columns
543
+
544
+ @insert_columns.setter
545
+ def insert_columns(self, value):
546
+ self._insert_columns = value
547
+
548
+ @property
549
+ def insert_rows(self):
550
+ """Whether to allow inserting rows."""
551
+ return self._insert_rows
552
+
553
+ @insert_rows.setter
554
+ def insert_rows(self, value):
555
+ self._insert_rows = value
556
+
557
+ @property
558
+ def insert_hyperlinks(self):
559
+ """Whether to allow inserting hyperlinks."""
560
+ return self._insert_hyperlinks
561
+
562
+ @insert_hyperlinks.setter
563
+ def insert_hyperlinks(self, value):
564
+ self._insert_hyperlinks = value
565
+
566
+ @property
567
+ def delete_columns(self):
568
+ """Whether to allow deleting columns."""
569
+ return self._delete_columns
570
+
571
+ @delete_columns.setter
572
+ def delete_columns(self, value):
573
+ self._delete_columns = value
574
+
575
+ @property
576
+ def delete_rows(self):
577
+ """Whether to allow deleting rows."""
578
+ return self._delete_rows
579
+
580
+ @delete_rows.setter
581
+ def delete_rows(self, value):
582
+ self._delete_rows = value
583
+
584
+ @property
585
+ def select_locked_cells(self):
586
+ """Whether to allow selecting locked cells."""
587
+ return self._select_locked_cells
588
+
589
+ @select_locked_cells.setter
590
+ def select_locked_cells(self, value):
591
+ self._select_locked_cells = value
592
+
593
+ @property
594
+ def sort(self):
595
+ """Whether to allow sorting."""
596
+ return self._sort
597
+
598
+ @sort.setter
599
+ def sort(self, value):
600
+ self._sort = value
601
+
602
+ @property
603
+ def auto_filter(self):
604
+ """Whether to allow using autoFilter."""
605
+ return self._auto_filter
606
+
607
+ @auto_filter.setter
608
+ def auto_filter(self, value):
609
+ self._auto_filter = value
610
+
611
+ @property
612
+ def pivot_tables(self):
613
+ """Whether to allow using pivot tables."""
614
+ return self._pivot_tables
615
+
616
+ @pivot_tables.setter
617
+ def pivot_tables(self, value):
618
+ self._pivot_tables = value
619
+
620
+ @property
621
+ def select_unlocked_cells(self):
622
+ """Whether to allow selecting unlocked cells."""
623
+ return self._select_unlocked_cells
624
+
625
+ @select_unlocked_cells.setter
626
+ def select_unlocked_cells(self, value):
627
+ self._select_unlocked_cells = value
628
+
629
+ @property
630
+ def password(self):
631
+ """Protection password (hashed)."""
632
+ return self._password
633
+
634
+ @password.setter
635
+ def password(self, value):
636
+ self._password = value
637
+
638
+ @property
639
+ def algorithm_name(self):
640
+ """Hash algorithm name (for modern protection)."""
641
+ return self._algorithm_name
642
+
643
+ @algorithm_name.setter
644
+ def algorithm_name(self, value):
645
+ self._algorithm_name = value
646
+
647
+ @property
648
+ def hash_value(self):
649
+ """Password hash (base64)."""
650
+ return self._hash_value
651
+
652
+ @hash_value.setter
653
+ def hash_value(self, value):
654
+ self._hash_value = value
655
+
656
+ @property
657
+ def salt_value(self):
658
+ """Salt for hashing (base64)."""
659
+ return self._salt_value
660
+
661
+ @salt_value.setter
662
+ def salt_value(self, value):
663
+ self._salt_value = value
664
+
665
+ @property
666
+ def spin_count(self):
667
+ """Number of hash iterations."""
668
+ return self._spin_count
669
+
670
+ @spin_count.setter
671
+ def spin_count(self, value):
672
+ self._spin_count = value
673
+
674
+ @property
675
+ def is_protected(self):
676
+ """Returns True if sheet protection is enabled."""
677
+ return self._sheet
678
+
679
+
680
+ class PageSetup:
681
+ """
682
+ Represents page setup settings.
683
+
684
+ ECMA-376 Section: 18.3.1.63
685
+
686
+ Examples:
687
+ >>> ws.properties.page_setup.orientation = "landscape"
688
+ >>> ws.properties.page_setup.paper_size = 9 # A4
689
+ >>> ws.properties.page_setup.scale = 80
690
+ """
691
+
692
+ def __init__(self):
693
+ self._paper_size = 1 # Letter
694
+ self._scale = 100
695
+ self._first_page_number = None
696
+ self._fit_to_width = None
697
+ self._fit_to_height = None
698
+ self._page_order = 'downThenOver'
699
+ self._orientation = 'portrait'
700
+ self._use_printer_defaults = True
701
+ self._black_and_white = False
702
+ self._draft = False
703
+ self._cell_comments = 'none'
704
+ self._errors = 'displayed'
705
+ self._horizontal_dpi = None
706
+ self._vertical_dpi = None
707
+ self._copies = 1
708
+
709
+ @property
710
+ def paper_size(self):
711
+ """Paper size (1=Letter, 9=A4, etc.)."""
712
+ return self._paper_size
713
+
714
+ @paper_size.setter
715
+ def paper_size(self, value):
716
+ self._paper_size = value
717
+
718
+ @property
719
+ def scale(self):
720
+ """Print scaling (10-400)."""
721
+ return self._scale
722
+
723
+ @scale.setter
724
+ def scale(self, value):
725
+ if value < 10 or value > 400:
726
+ raise ValueError("scale must be between 10 and 400")
727
+ self._scale = value
728
+
729
+ @property
730
+ def first_page_number(self):
731
+ """First page number."""
732
+ return self._first_page_number
733
+
734
+ @first_page_number.setter
735
+ def first_page_number(self, value):
736
+ self._first_page_number = value
737
+
738
+ @property
739
+ def fit_to_width(self):
740
+ """Fit to width pages (0 = use scale)."""
741
+ return self._fit_to_width
742
+
743
+ @fit_to_width.setter
744
+ def fit_to_width(self, value):
745
+ self._fit_to_width = value
746
+
747
+ @property
748
+ def fit_to_height(self):
749
+ """Fit to height pages (0 = use scale)."""
750
+ return self._fit_to_height
751
+
752
+ @fit_to_height.setter
753
+ def fit_to_height(self, value):
754
+ self._fit_to_height = value
755
+
756
+ @property
757
+ def page_order(self):
758
+ """Page order: 'downThenOver' or 'overThenDown'."""
759
+ return self._page_order
760
+
761
+ @page_order.setter
762
+ def page_order(self, value):
763
+ if value not in ('downThenOver', 'overThenDown'):
764
+ raise ValueError("page_order must be 'downThenOver' or 'overThenDown'")
765
+ self._page_order = value
766
+
767
+ @property
768
+ def orientation(self):
769
+ """Page orientation: 'portrait' or 'landscape'."""
770
+ return self._orientation
771
+
772
+ @orientation.setter
773
+ def orientation(self, value):
774
+ if value not in ('portrait', 'landscape'):
775
+ raise ValueError("orientation must be 'portrait' or 'landscape'")
776
+ self._orientation = value
777
+
778
+ @property
779
+ def use_printer_defaults(self):
780
+ """Whether to use printer defaults."""
781
+ return self._use_printer_defaults
782
+
783
+ @use_printer_defaults.setter
784
+ def use_printer_defaults(self, value):
785
+ self._use_printer_defaults = value
786
+
787
+ @property
788
+ def black_and_white(self):
789
+ """Whether to print in black and white."""
790
+ return self._black_and_white
791
+
792
+ @black_and_white.setter
793
+ def black_and_white(self, value):
794
+ self._black_and_white = value
795
+
796
+ @property
797
+ def draft(self):
798
+ """Whether to print in draft quality."""
799
+ return self._draft
800
+
801
+ @draft.setter
802
+ def draft(self, value):
803
+ self._draft = value
804
+
805
+ @property
806
+ def copies(self):
807
+ """Number of copies."""
808
+ return self._copies
809
+
810
+ @copies.setter
811
+ def copies(self, value):
812
+ self._copies = value
813
+
814
+ @property
815
+ def cell_comments(self):
816
+ """Print cell comments: 'none', 'atEnd', or 'asDisplayed'."""
817
+ return self._cell_comments
818
+
819
+ @cell_comments.setter
820
+ def cell_comments(self, value):
821
+ self._cell_comments = value
822
+
823
+ @property
824
+ def errors(self):
825
+ """Print errors: 'displayed', 'blank', 'dash', or 'NA'."""
826
+ return self._errors
827
+
828
+ @errors.setter
829
+ def errors(self, value):
830
+ self._errors = value
831
+
832
+ @property
833
+ def horizontal_dpi(self):
834
+ """Horizontal DPI for printing."""
835
+ return self._horizontal_dpi
836
+
837
+ @horizontal_dpi.setter
838
+ def horizontal_dpi(self, value):
839
+ self._horizontal_dpi = value
840
+
841
+ @property
842
+ def vertical_dpi(self):
843
+ """Vertical DPI for printing."""
844
+ return self._vertical_dpi
845
+
846
+ @vertical_dpi.setter
847
+ def vertical_dpi(self, value):
848
+ self._vertical_dpi = value
849
+
850
+ @property
851
+ def use_first_page_number(self):
852
+ """Whether to use the first page number."""
853
+ return self._first_page_number is not None
854
+
855
+ @use_first_page_number.setter
856
+ def use_first_page_number(self, value):
857
+ if value:
858
+ if self._first_page_number is None:
859
+ self._first_page_number = 1
860
+ else:
861
+ self._first_page_number = None
862
+
863
+ @property
864
+ def fit_to_page(self):
865
+ """Whether to fit to page (True if fit_to_width or fit_to_height is set)."""
866
+ return self._fit_to_width is not None or self._fit_to_height is not None
867
+
868
+ @fit_to_page.setter
869
+ def fit_to_page(self, value):
870
+ """Enable or disable fit to page mode."""
871
+ if value:
872
+ # Enable fit to page with default values if not already set
873
+ if self._fit_to_width is None:
874
+ self._fit_to_width = 1
875
+ if self._fit_to_height is None:
876
+ self._fit_to_height = 1
877
+ else:
878
+ # Disable fit to page
879
+ self._fit_to_width = None
880
+ self._fit_to_height = None
881
+
882
+
883
+ class PageMargins:
884
+ """
885
+ Represents page margins.
886
+
887
+ ECMA-376 Section: 18.3.1.62
888
+
889
+ Examples:
890
+ >>> ws.properties.page_margins.left = 0.7
891
+ >>> ws.properties.page_margins.top = 0.75
892
+ """
893
+
894
+ def __init__(self):
895
+ self._left = 0.7
896
+ self._right = 0.7
897
+ self._top = 0.75
898
+ self._bottom = 0.75
899
+ self._header = 0.3
900
+ self._footer = 0.3
901
+
902
+ @property
903
+ def left(self):
904
+ """Left margin in inches."""
905
+ return self._left
906
+
907
+ @left.setter
908
+ def left(self, value):
909
+ self._left = value
910
+
911
+ @property
912
+ def right(self):
913
+ """Right margin in inches."""
914
+ return self._right
915
+
916
+ @right.setter
917
+ def right(self, value):
918
+ self._right = value
919
+
920
+ @property
921
+ def top(self):
922
+ """Top margin in inches."""
923
+ return self._top
924
+
925
+ @top.setter
926
+ def top(self, value):
927
+ self._top = value
928
+
929
+ @property
930
+ def bottom(self):
931
+ """Bottom margin in inches."""
932
+ return self._bottom
933
+
934
+ @bottom.setter
935
+ def bottom(self, value):
936
+ self._bottom = value
937
+
938
+ @property
939
+ def header(self):
940
+ """Header margin in inches."""
941
+ return self._header
942
+
943
+ @header.setter
944
+ def header(self, value):
945
+ self._header = value
946
+
947
+ @property
948
+ def footer(self):
949
+ """Footer margin in inches."""
950
+ return self._footer
951
+
952
+ @footer.setter
953
+ def footer(self, value):
954
+ self._footer = value
955
+
956
+
957
+ class HeaderFooter:
958
+ """
959
+ Represents header and footer settings.
960
+
961
+ ECMA-376 Section: 18.3.1.46
962
+
963
+ Examples:
964
+ >>> ws.properties.header_footer.odd_header = "&C&\"Arial,Bold\"Report Title"
965
+ >>> ws.properties.header_footer.odd_footer = "&CPage &P of &N"
966
+ """
967
+
968
+ def __init__(self):
969
+ self._different_first = False
970
+ self._different_odd_even = False
971
+ self._scale_with_doc = True
972
+ self._align_with_margins = True
973
+ self._odd_header = None
974
+ self._odd_footer = None
975
+ self._even_header = None
976
+ self._even_footer = None
977
+ self._first_header = None
978
+ self._first_footer = None
979
+
980
+ @property
981
+ def different_first(self):
982
+ """Whether to have different first page header/footer."""
983
+ return self._different_first
984
+
985
+ @different_first.setter
986
+ def different_first(self, value):
987
+ self._different_first = value
988
+
989
+ @property
990
+ def different_odd_even(self):
991
+ """Whether to have different odd/even page headers/footers."""
992
+ return self._different_odd_even
993
+
994
+ @different_odd_even.setter
995
+ def different_odd_even(self, value):
996
+ self._different_odd_even = value
997
+
998
+ @property
999
+ def scale_with_doc(self):
1000
+ """Whether to scale with document."""
1001
+ return self._scale_with_doc
1002
+
1003
+ @scale_with_doc.setter
1004
+ def scale_with_doc(self, value):
1005
+ self._scale_with_doc = value
1006
+
1007
+ @property
1008
+ def align_with_margins(self):
1009
+ """Whether to align with margins."""
1010
+ return self._align_with_margins
1011
+
1012
+ @align_with_margins.setter
1013
+ def align_with_margins(self, value):
1014
+ self._align_with_margins = value
1015
+
1016
+ @property
1017
+ def odd_header(self):
1018
+ """Header for odd pages (or all pages if not different_odd_even)."""
1019
+ return self._odd_header
1020
+
1021
+ @odd_header.setter
1022
+ def odd_header(self, value):
1023
+ self._odd_header = value
1024
+
1025
+ @property
1026
+ def odd_footer(self):
1027
+ """Footer for odd pages (or all pages if not different_odd_even)."""
1028
+ return self._odd_footer
1029
+
1030
+ @odd_footer.setter
1031
+ def odd_footer(self, value):
1032
+ self._odd_footer = value
1033
+
1034
+ @property
1035
+ def even_header(self):
1036
+ """Header for even pages."""
1037
+ return self._even_header
1038
+
1039
+ @even_header.setter
1040
+ def even_header(self, value):
1041
+ self._even_header = value
1042
+
1043
+ @property
1044
+ def even_footer(self):
1045
+ """Footer for even pages."""
1046
+ return self._even_footer
1047
+
1048
+ @even_footer.setter
1049
+ def even_footer(self, value):
1050
+ self._even_footer = value
1051
+
1052
+ @property
1053
+ def first_header(self):
1054
+ """Header for first page."""
1055
+ return self._first_header
1056
+
1057
+ @first_header.setter
1058
+ def first_header(self, value):
1059
+ self._first_header = value
1060
+
1061
+ @property
1062
+ def first_footer(self):
1063
+ """Footer for first page."""
1064
+ return self._first_footer
1065
+
1066
+ @first_footer.setter
1067
+ def first_footer(self, value):
1068
+ self._first_footer = value
1069
+
1070
+
1071
+ class PrintOptions:
1072
+ """
1073
+ Represents print options.
1074
+
1075
+ ECMA-376 Section: 18.3.1.70
1076
+
1077
+ Examples:
1078
+ >>> ws.properties.print_options.print_grid_lines = True
1079
+ >>> ws.properties.print_options.print_headings = True
1080
+ """
1081
+
1082
+ def __init__(self):
1083
+ self._print_headings = False
1084
+ self._print_grid_lines = False
1085
+ self._grid_lines_set = True
1086
+ self._horizontal_centered = False
1087
+ self._vertical_centered = False
1088
+ self._black_and_white = False
1089
+ self._draft_quality = False
1090
+ self._cell_comments = 'none'
1091
+ self._print_errors = 'displayed'
1092
+
1093
+ @property
1094
+ def print_headings(self):
1095
+ """Whether to print row and column headings."""
1096
+ return self._print_headings
1097
+
1098
+ @print_headings.setter
1099
+ def print_headings(self, value):
1100
+ self._print_headings = value
1101
+
1102
+ @property
1103
+ def print_grid_lines(self):
1104
+ """Whether to print grid lines."""
1105
+ return self._print_grid_lines
1106
+
1107
+ @print_grid_lines.setter
1108
+ def print_grid_lines(self, value):
1109
+ self._print_grid_lines = value
1110
+
1111
+ @property
1112
+ def horizontal_centered(self):
1113
+ """Whether to center horizontally on page."""
1114
+ return self._horizontal_centered
1115
+
1116
+ @horizontal_centered.setter
1117
+ def horizontal_centered(self, value):
1118
+ self._horizontal_centered = value
1119
+
1120
+ @property
1121
+ def vertical_centered(self):
1122
+ """Whether to center vertically on page."""
1123
+ return self._vertical_centered
1124
+
1125
+ @vertical_centered.setter
1126
+ def vertical_centered(self, value):
1127
+ self._vertical_centered = value
1128
+
1129
+ @property
1130
+ def print_gridlines(self):
1131
+ """Alias for print_grid_lines property."""
1132
+ return self._print_grid_lines
1133
+
1134
+ @print_gridlines.setter
1135
+ def print_gridlines(self, value):
1136
+ self._print_grid_lines = value
1137
+
1138
+ @property
1139
+ def black_and_white(self):
1140
+ """Whether to print in black and white."""
1141
+ return self._black_and_white
1142
+
1143
+ @black_and_white.setter
1144
+ def black_and_white(self, value):
1145
+ self._black_and_white = value
1146
+
1147
+ @property
1148
+ def draft_quality(self):
1149
+ """Whether to print in draft quality."""
1150
+ return self._draft_quality
1151
+
1152
+ @draft_quality.setter
1153
+ def draft_quality(self, value):
1154
+ self._draft_quality = value
1155
+
1156
+ @property
1157
+ def cell_comments(self):
1158
+ """Print cell comments: 'none', 'atEnd', or 'asDisplayed'."""
1159
+ return self._cell_comments
1160
+
1161
+ @cell_comments.setter
1162
+ def cell_comments(self, value):
1163
+ self._cell_comments = value
1164
+
1165
+ @property
1166
+ def print_errors(self):
1167
+ """Print errors: 'displayed', 'blank', 'dash', or 'NA'."""
1168
+ return self._print_errors
1169
+
1170
+ @print_errors.setter
1171
+ def print_errors(self, value):
1172
+ self._print_errors = value
1173
+
1174
+
1175
+ class WorksheetProperties:
1176
+ """
1177
+ Container for all worksheet-level properties.
1178
+
1179
+ Examples:
1180
+ >>> ws.properties.view.show_grid_lines = False
1181
+ >>> ws.properties.protection.sheet = True
1182
+ >>> ws.properties.page_setup.orientation = "landscape"
1183
+ """
1184
+
1185
+ def __init__(self):
1186
+ self._view = SheetView()
1187
+ self._selection = Selection()
1188
+ self._pane = Pane()
1189
+ self._format = SheetFormatProperties()
1190
+ self._protection = SheetProtection()
1191
+ self._page_setup = PageSetup()
1192
+ self._page_margins = PageMargins()
1193
+ self._header_footer = HeaderFooter()
1194
+ self._print_options = PrintOptions()
1195
+
1196
+ @property
1197
+ def view(self):
1198
+ """Gets sheet view settings."""
1199
+ return self._view
1200
+
1201
+ @property
1202
+ def selection(self):
1203
+ """Gets selection settings."""
1204
+ return self._selection
1205
+
1206
+ @property
1207
+ def pane(self):
1208
+ """Gets pane (freeze/split) settings."""
1209
+ return self._pane
1210
+
1211
+ @property
1212
+ def format(self):
1213
+ """Gets sheet format properties."""
1214
+ return self._format
1215
+
1216
+ @property
1217
+ def protection(self):
1218
+ """Gets sheet protection settings."""
1219
+ return self._protection
1220
+
1221
+ @property
1222
+ def page_setup(self):
1223
+ """Gets page setup settings."""
1224
+ return self._page_setup
1225
+
1226
+ @property
1227
+ def page_margins(self):
1228
+ """Gets page margins."""
1229
+ return self._page_margins
1230
+
1231
+ @property
1232
+ def header_footer(self):
1233
+ """Gets header and footer settings."""
1234
+ return self._header_footer
1235
+
1236
+ @property
1237
+ def print_options(self):
1238
+ """Gets print options."""
1239
+ return self._print_options