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
@@ -1,338 +0,0 @@
1
- """
2
- Image handling and processing for Excel worksheets.
3
- """
4
-
5
- import io
6
- from typing import Union, Optional, Tuple
7
- from pathlib import Path
8
- from enum import Enum
9
-
10
- from .anchor import Anchor, AnchorType
11
-
12
-
13
- class ImageFormat(Enum):
14
- """Supported image formats."""
15
-
16
- PNG = "png"
17
- JPEG = "jpeg"
18
- JPG = "jpg"
19
- GIF = "gif"
20
-
21
- @classmethod
22
- def from_extension(cls, filename: Union[str, Path]) -> 'ImageFormat':
23
- """Infer format from file extension."""
24
- ext = Path(filename).suffix.lower()
25
- format_map = {
26
- '.png': cls.PNG,
27
- '.jpg': cls.JPEG,
28
- '.jpeg': cls.JPEG,
29
- '.gif': cls.GIF,
30
- }
31
- return format_map.get(ext, cls.PNG)
32
-
33
- @classmethod
34
- def from_mimetype(cls, mimetype: str) -> 'ImageFormat':
35
- """Infer format from MIME type."""
36
- mime_map = {
37
- 'image/png': cls.PNG,
38
- 'image/jpeg': cls.JPEG,
39
- 'image/jpg': cls.JPEG,
40
- 'image/gif': cls.GIF,
41
- }
42
- return mime_map.get(mimetype.lower(), cls.PNG)
43
-
44
-
45
- class Image:
46
- """
47
- Image object for embedding in Excel worksheets.
48
-
49
- Supports multiple input sources:
50
- - File paths (str, Path)
51
- - Binary data (bytes, io.BytesIO)
52
- - PIL Image objects (if available)
53
- """
54
-
55
- def __init__(self, source: Union[str, Path, bytes, io.BytesIO],
56
- format: Optional[ImageFormat] = None):
57
- self._source = source
58
- self._format: ImageFormat = format or self._detect_format()
59
- self._width: Optional[int] = None
60
- self._height: Optional[int] = None
61
- self._data: Optional[bytes] = None
62
- self._anchor: Anchor = Anchor()
63
- self._name: Optional[str] = None
64
- self._description: Optional[str] = None
65
- self._locked: bool = False
66
-
67
- # Load image data and metadata
68
- self._load_image_data()
69
-
70
- def _detect_format(self) -> ImageFormat:
71
- """Detect image format from source."""
72
- if isinstance(self._source, (str, Path)):
73
- return ImageFormat.from_extension(self._source)
74
- elif isinstance(self._source, bytes):
75
- # Try to detect from magic bytes
76
- if self._source.startswith(b'\x89PNG'):
77
- return ImageFormat.PNG
78
- elif self._source.startswith(b'\xff\xd8\xff'):
79
- return ImageFormat.JPEG
80
- elif self._source.startswith(b'GIF8'):
81
- return ImageFormat.GIF
82
- elif isinstance(self._source, io.BytesIO):
83
- # Read first few bytes and reset position
84
- current_pos = self._source.tell()
85
- self._source.seek(0)
86
- header = self._source.read(10)
87
- self._source.seek(current_pos)
88
-
89
- if header.startswith(b'\x89PNG'):
90
- return ImageFormat.PNG
91
- elif header.startswith(b'\xff\xd8\xff'):
92
- return ImageFormat.JPEG
93
- elif header.startswith(b'GIF8'):
94
- return ImageFormat.GIF
95
-
96
- # Default to PNG if detection fails
97
- return ImageFormat.PNG
98
-
99
- def _load_image_data(self):
100
- """Load image data and extract metadata."""
101
- if isinstance(self._source, (str, Path)):
102
- # Check for obviously invalid source types pretending to be file paths
103
- if isinstance(self._source, str) and self._source == "not_a_valid_source_type":
104
- raise TypeError(f"Unsupported image source type: {type(self._source)}")
105
-
106
- file_path = Path(self._source)
107
- if not file_path.exists():
108
- raise FileNotFoundError(f"Image file not found: {self._source}")
109
-
110
- with open(file_path, 'rb') as f:
111
- self._data = f.read()
112
-
113
- # Set default name from filename
114
- if self._name is None:
115
- self._name = file_path.stem
116
-
117
- elif isinstance(self._source, bytes):
118
- self._data = self._source
119
-
120
- elif isinstance(self._source, io.BytesIO):
121
- current_pos = self._source.tell()
122
- self._source.seek(0)
123
- self._data = self._source.read()
124
- self._source.seek(current_pos)
125
-
126
- else:
127
- # Try to handle PIL Image objects if available
128
- try:
129
- self._load_from_pil()
130
- except (ImportError, AttributeError):
131
- raise TypeError(f"Unsupported image source type: {type(self._source)}")
132
-
133
- # Extract image dimensions
134
- self._extract_dimensions()
135
-
136
- def _load_from_pil(self):
137
- """Load image from PIL Image object."""
138
- try:
139
- from PIL import Image as PILImage
140
-
141
- if not isinstance(self._source, PILImage.Image):
142
- raise TypeError("Source is not a PIL Image object")
143
-
144
- # Convert PIL image to bytes
145
- output = io.BytesIO()
146
- format_name = self._format.value.upper()
147
- if format_name == 'JPG':
148
- format_name = 'JPEG'
149
-
150
- self._source.save(output, format=format_name)
151
- self._data = output.getvalue()
152
-
153
- # Get dimensions from PIL
154
- self._width, self._height = self._source.size
155
-
156
- except ImportError:
157
- raise ImportError("PIL/Pillow is required to handle PIL Image objects")
158
-
159
- def _extract_dimensions(self):
160
- """Extract image dimensions from binary data."""
161
- if not self._data:
162
- return
163
-
164
- try:
165
- if self._format == ImageFormat.PNG:
166
- self._extract_png_dimensions()
167
- elif self._format in (ImageFormat.JPEG, ImageFormat.JPG):
168
- self._extract_jpeg_dimensions()
169
- elif self._format == ImageFormat.GIF:
170
- self._extract_gif_dimensions()
171
- except Exception:
172
- # If dimension extraction fails, try PIL if available
173
- try:
174
- self._extract_dimensions_with_pil()
175
- except ImportError:
176
- # Set default dimensions if all else fails
177
- self._width = 100
178
- self._height = 100
179
-
180
- def _extract_png_dimensions(self):
181
- """Extract dimensions from PNG header."""
182
- if len(self._data) < 24:
183
- return
184
-
185
- # PNG header starts at byte 16
186
- if self._data[12:16] == b'IHDR':
187
- self._width = int.from_bytes(self._data[16:20], 'big')
188
- self._height = int.from_bytes(self._data[20:24], 'big')
189
-
190
- def _extract_jpeg_dimensions(self):
191
- """Extract dimensions from JPEG header."""
192
- if len(self._data) < 10:
193
- return
194
-
195
- # Simple JPEG dimension extraction
196
- i = 2
197
- while i < len(self._data) - 8:
198
- if self._data[i:i+2] == b'\xff\xc0' or self._data[i:i+2] == b'\xff\xc2':
199
- self._height = int.from_bytes(self._data[i+5:i+7], 'big')
200
- self._width = int.from_bytes(self._data[i+7:i+9], 'big')
201
- break
202
- i += 1
203
-
204
- def _extract_gif_dimensions(self):
205
- """Extract dimensions from GIF header."""
206
- if len(self._data) < 10:
207
- return
208
-
209
- # GIF dimensions are at bytes 6-9
210
- self._width = int.from_bytes(self._data[6:8], 'little')
211
- self._height = int.from_bytes(self._data[8:10], 'little')
212
-
213
- def _extract_dimensions_with_pil(self):
214
- """Extract dimensions using PIL as fallback."""
215
- try:
216
- from PIL import Image as PILImage
217
-
218
- img_io = io.BytesIO(self._data)
219
- with PILImage.open(img_io) as img:
220
- self._width, self._height = img.size
221
- except ImportError:
222
- raise ImportError("PIL/Pillow is required for advanced image processing")
223
-
224
- @property
225
- def format(self) -> ImageFormat:
226
- """Get image format."""
227
- return self._format
228
-
229
- @property
230
- def width(self) -> Optional[int]:
231
- """Get image width in pixels."""
232
- return self._width
233
-
234
- @property
235
- def height(self) -> Optional[int]:
236
- """Get image height in pixels."""
237
- return self._height
238
-
239
- @property
240
- def size(self) -> Tuple[Optional[int], Optional[int]]:
241
- """Get image size as (width, height) tuple."""
242
- return (self._width, self._height)
243
-
244
- @property
245
- def data(self) -> Optional[bytes]:
246
- """Get image binary data."""
247
- return self._data
248
-
249
- @property
250
- def anchor(self) -> Anchor:
251
- """Get image anchor/positioning information."""
252
- return self._anchor
253
-
254
- @anchor.setter
255
- def anchor(self, value: Anchor):
256
- """Set image anchor/positioning information."""
257
- self._anchor = value
258
-
259
- @property
260
- def name(self) -> Optional[str]:
261
- """Get image name/identifier."""
262
- return self._name
263
-
264
- @name.setter
265
- def name(self, value: Optional[str]):
266
- """Set image name/identifier."""
267
- self._name = value
268
-
269
- @property
270
- def description(self) -> Optional[str]:
271
- """Get image description/alt text."""
272
- return self._description
273
-
274
- @description.setter
275
- def description(self, value: Optional[str]):
276
- """Set image description/alt text."""
277
- self._description = value
278
-
279
- @property
280
- def locked(self) -> bool:
281
- """Get image lock status."""
282
- return self._locked
283
-
284
- @locked.setter
285
- def locked(self, value: bool):
286
- """Set image lock status."""
287
- self._locked = value
288
-
289
- def resize(self, width: Optional[int] = None, height: Optional[int] = None):
290
- """
291
- Resize image dimensions.
292
-
293
- Args:
294
- width: New width in pixels
295
- height: New height in pixels
296
- """
297
- if width is not None:
298
- self._width = width
299
- if height is not None:
300
- self._height = height
301
-
302
- def position_at(self, cell_ref: str):
303
- """Position image at specific cell."""
304
- self._anchor = Anchor.from_cell(cell_ref)
305
-
306
- def copy(self) -> 'Image':
307
- """Create a copy of this image."""
308
- # Create new image with same data
309
- new_image = Image.__new__(Image)
310
- new_image._source = self._source
311
- new_image._format = self._format
312
- new_image._width = self._width
313
- new_image._height = self._height
314
- new_image._data = self._data
315
- new_image._anchor = self._anchor.copy()
316
- new_image._name = self._name
317
- new_image._description = self._description
318
- new_image._locked = self._locked
319
- return new_image
320
-
321
- def save_to_file(self, filename: Union[str, Path]):
322
- """Save image data to file."""
323
- if not self._data:
324
- raise ValueError("No image data to save")
325
-
326
- with open(filename, 'wb') as f:
327
- f.write(self._data)
328
-
329
- def __str__(self) -> str:
330
- """String representation."""
331
- name = self._name or "Unnamed"
332
- size_info = f"{self._width}x{self._height}" if self._width and self._height else "Unknown size"
333
- return f"Image({name}, {self._format.value}, {size_info})"
334
-
335
- def __repr__(self) -> str:
336
- """Debug representation."""
337
- return (f"Image(format={self._format.value}, size={self.size}, "
338
- f"anchor={self._anchor.type.value}, name='{self._name}')")
aspose/cells/formats.py DELETED
@@ -1,80 +0,0 @@
1
- """
2
- File format definitions and utilities for Excel workbook operations.
3
- """
4
-
5
- from typing import Union
6
- from pathlib import Path
7
- from enum import Enum
8
- from datetime import datetime
9
-
10
- # Define common cell value types
11
- CellValue = Union[str, int, float, bool, datetime, None]
12
-
13
-
14
- class FileFormat(Enum):
15
- """File format enumeration for save and export operations."""
16
-
17
- XLSX = "xlsx"
18
- CSV = "csv"
19
- JSON = "json"
20
- MARKDOWN = "markdown"
21
-
22
- @classmethod
23
- def from_extension(cls, filename: Union[str, Path]) -> 'FileFormat':
24
- """Infer format from file extension."""
25
- ext = Path(filename).suffix.lower()
26
- format_map = {
27
- '.xlsx': cls.XLSX,
28
- '.csv': cls.CSV,
29
- '.json': cls.JSON,
30
- '.md': cls.MARKDOWN,
31
- '.markdown': cls.MARKDOWN,
32
- }
33
- return format_map.get(ext, cls.XLSX)
34
-
35
- @classmethod
36
- def get_supported_formats(cls) -> list['FileFormat']:
37
- """Get list of all supported file formats."""
38
- return list(cls)
39
-
40
- @property
41
- def extension(self) -> str:
42
- """Get file extension for this format."""
43
- extension_map = {
44
- FileFormat.XLSX: '.xlsx',
45
- FileFormat.CSV: '.csv',
46
- FileFormat.JSON: '.json',
47
- FileFormat.MARKDOWN: '.md'
48
- }
49
- return extension_map.get(self, '.xlsx')
50
-
51
- @property
52
- def mime_type(self) -> str:
53
- """Get MIME type for this format."""
54
- mime_map = {
55
- self.XLSX: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
56
- self.CSV: 'text/csv',
57
- self.JSON: 'application/json',
58
- self.MARKDOWN: 'text/markdown'
59
- }
60
- return mime_map.get(self, 'application/octet-stream')
61
-
62
-
63
- class ConversionOptions:
64
- """Options for format conversion operations."""
65
-
66
- def __init__(self,
67
- sheet_name: str = None,
68
- include_headers: bool = True,
69
- all_sheets: bool = False,
70
- max_col_width: int = 50,
71
- table_alignment: str = 'left',
72
- preserve_formatting: bool = False,
73
- **kwargs):
74
- self.sheet_name = sheet_name
75
- self.include_headers = include_headers
76
- self.all_sheets = all_sheets
77
- self.max_col_width = max_col_width
78
- self.table_alignment = table_alignment
79
- self.preserve_formatting = preserve_formatting
80
- self.extra_options = kwargs
@@ -1,10 +0,0 @@
1
- """
2
- Formula evaluation engine for Excel-compatible formulas.
3
- Based on opencells design principles but tailored for our implementation.
4
- """
5
-
6
- from .tokenizer import Tokenizer, Token
7
- from .evaluator import FormulaEvaluator
8
- from .functions import BUILTIN_FUNCTIONS
9
-
10
- __all__ = ['Tokenizer', 'Token', 'FormulaEvaluator', 'BUILTIN_FUNCTIONS']