symphra-excel


Namesymphra-excel JSON
Version 0.0.1 PyPI version JSON
download
home_pageNone
SummaryHigh-performance Excel processing library for Python 3.11+
upload_time2025-11-02 06:59:30
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseNone
keywords excel spreadsheet xlsx template high-performance
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Symphra Excel Library

一个功能强大的Python Excel处理库,提供现代化的API接口、高性能的数据处理能力和丰富的样式支持。

## 功能特性

- 🚀 **现代化API设计** - 简洁直观的接口,易于使用
- 🎨 **丰富的样式系统** - 支持字体、颜色、边框、对齐等完整样式设置
- 📊 **模板引擎** - 基于Jinja2的模板渲染系统
- ⚡ **异步支持** - 提供异步API接口,支持并发处理
- 💾 **内存优化** - 高效的内存管理和大数据量处理能力
- 🖼️ **图片处理** - 支持Excel中插入图片和嵌入单元格功能
- 🔧 **扩展性强** - 模块化设计,易于扩展和定制

## 项目状态(2025-10-31)

- ✅ **核心功能完整**:同步/异步 `Workbook` 与 `Worksheet` API 支持读写模式切换、批量写入、样式管理、图片插入
- ✅ **测试覆盖充分**:49个pytest测试用例全部通过,包括同步/异步/模板/样式等核心功能
- ✅ **类型安全改善**:mypy核心库错误从292个降至32个(减少89%),剩余错误不影响运行
- 🎨 **模板引擎可用**:基于Jinja2沙箱的模板系统,支持循环/条件/图片占位,参考 `examples/03_template_examples.py`
- 🚀 **生产可用**:核心API稳定,适合中小规模Excel处理需求
- 📚 **文档完善中**:API文档和更多示例持续补充中

## 快速开始

### 安装

```bash
pip install symphra-excel
```

### 5分钟快速上手

最简单的Excel生成示例(完整代码见 [quickstart.py](quickstart.py)):

```python
from symphra_excel import Workbook, PredefinedStyles

# 1. 创建工作簿和工作表
wb = Workbook()
sheet = wb.create_worksheet("销售数据")

# 2. 写入表头并应用预定义样式
headers = ["产品名称", "销量", "单价", "总额"]
for col_idx, header in enumerate(headers):
    cell_ref = f"{chr(65 + col_idx)}1"  # A1, B1, C1, D1
    sheet.set_cell_value(cell_ref, header)
    sheet.apply_style(cell_ref, PredefinedStyles.header_style())

# 3. 写入数据
data = [
    ["iPhone 15", 100, 5999, 599900],
    ["MacBook Pro", 50, 12999, 649950],
    ["AirPods Pro", 200, 1999, 399800],
]
for row_idx, row_data in enumerate(data, start=2):
    for col_idx, value in enumerate(row_data):
        cell_ref = f"{chr(65 + col_idx)}{row_idx}"
        sheet.set_cell_value(cell_ref, value)

# 4. 保存文件
wb.save("销售报表.xlsx")
```

运行以上代码将生成一个包含样式的专业Excel报表!

## 详细文档

### 核心模块

#### 工作簿和工作表操作

```python
from symphra_excel import Workbook

# 创建工作簿
workbook = Workbook()

# 创建工作表
sheet1 = workbook.create_worksheet('数据表1')
sheet2 = workbook.create_worksheet('数据表2')

# 获取工作表
sheet = workbook.get_worksheet('数据表1')

# 删除工作表
workbook.delete_worksheet('数据表2')

# 保存工作簿
workbook.save('输出文件.xlsx')

# 保存到内存
file_data = workbook.save_to_memory()
```

#### 性能模式

```python
from symphra_excel import Workbook

# 只读访问大文件(不会写回原文件)
readonly_wb = Workbook("report.xlsx", mode="read_only")
value = readonly_wb.get_worksheet("Sheet1").get_cell_value("A1")

# 写入流式导出,按行追加数据
stream_wb = Workbook(mode="write_only")
stream_sheet = stream_wb.create_worksheet("Stream")
stream_sheet.append_row(["姓名", "分数"])
stream_sheet.append_rows([["张三", 90], ["李四", 85]])
stream_wb.save("stream_output.xlsx")
```

#### 单元格操作

```python
# 设置单元格值
sheet.set_cell_value('A1', 'Hello World')
sheet.set_cell_value('B1', 123.45)
sheet.set_cell_value('C1', '=A1+B1')  # 公式

# 获取单元格值
value = sheet.get_cell_value('A1')

# 批量设置范围值
data = [
    ['姓名', '年龄', '城市'],
    ['张三', 25, '北京'],
    ['李四', 30, '上海']
]
sheet.set_range_values('A1:C3', data)

# 获取范围值
range_values = sheet.get_range_values('A1:C3')
```

#### 行列操作

```python
# 插入行
sheet.insert_rows(2, 3)  # 在第2行插入3行

# 删除行
sheet.delete_rows(2, 3)  # 从第2行开始删除3行

# 插入列
sheet.insert_columns(2, 2)  # 在第2列插入2列

# 删除列
sheet.delete_columns(2, 2)  # 从第2列开始删除2列
```

### 样式系统

#### 创建自定义样式

```python
from symphra_excel import CellStyle, Color

# 创建样式
style = CellStyle()

# 设置字体
style.set_font(
    name='微软雅黑',
    size=12,
    bold=True,
    italic=False,
    color=Color.WHITE
)

# 设置背景颜色
style.set_background_color(Color.DARK_BLUE)

# 设置边框
style.set_border(
    left=True, right=True, top=True, bottom=True,
    left_color=Color.BLACK,
    right_color=Color.BLACK,
    top_color=Color.BLACK,
    bottom_color=Color.BLACK
)

# 设置对齐方式
style.set_alignment(horizontal='center', vertical='center')

# 设置数字格式
style.set_number_format('0.00')

# 应用样式到单元格
sheet.set_cell_style('A1', style)
```

#### 使用预定义样式

```python
from symphra_excel import PredefinedStyles

# 表头样式
header_style = PredefinedStyles.header_style()
sheet.set_cell_style('A1', header_style)

# 标题样式
title_style = PredefinedStyles.title_style()
sheet.set_cell_style('A1', title_style)

# 高亮样式
highlight_style = PredefinedStyles.highlight_style()
sheet.set_cell_style('A2', highlight_style)

# 货币样式
currency_style = PredefinedStyles.currency_style()
sheet.set_cell_style('B2', currency_style)
```

#### 颜色系统

```python
from symphra_excel import Color, PredefinedStyles

# 使用预定义颜色
red = Color.RED
blue = Color.BLUE
green = Color.GREEN

# 使用十六进制颜色
hex_color = Color.from_hex('#FF6B35')

# 使用RGB颜色
rgb_color = Color.from_rgb(255, 107, 53)

# 使用主题颜色
primary_color = PredefinedStyles.get_theme_color('primary')
secondary_color = PredefinedStyles.get_theme_color('secondary')
```

### 模板引擎

#### 基本模板使用

```python
from symphra_excel import TemplateWorkbook

# 加载模板
template = TemplateWorkbook.load_template('report_template.xlsx')

# 准备数据
context = {
    'title': '月度销售报告',
    'date': '2024年1月',
    'total_sales': 150000,
    'products': [
        {'name': '产品A', 'sales': 50000},
        {'name': '产品B', 'sales': 75000},
        {'name': '产品C', 'sales': 25000}
    ]
}

# 渲染模板
workbook = template.render(context)

# 保存结果
workbook.save('生成的报告.xlsx')
```

#### 模板语法

支持Jinja2模板语法:

```excel
{{ title }}                    # 简单变量
{{ date.strftime('%Y-%m') }}   # 日期格式化
{% for product in products %}    # 循环
{{ product.name }}
{{ product.sales }}
{% endfor %}

{{ total_sales | number_format }}  # 数字格式化
{{ title | upper }}                # 文本转换
```

#### 循环与条件块设计

在模板中,循环/条件控制语句应独立占一整行,后续行用于放置实际单元格内容。例如:

```excel
{% for row in items %}
{{ row.name }}	{{ row.amount }}
{% endfor %}

{% if show_summary %}
汇总	{{ summary }}
{% endif %}
```

渲染时会自动展开循环并保留单元格格式;条件块在布尔表达式为 `False` 时将被整体移除。

#### 模板图片占位符

模板单元格可使用 `insert_image` 占位符延迟插图:

```excel
{{ insert_image(logo_path, width=120, height=60, maintain_aspect_ratio=True) }}
```

渲染后占位符所在单元格值会被清空,图片根据参数插入。

#### 上下文安全约束

- 仅允许传入 `str`、`int`、`float`、`bool`、`None` 以及由这些值组成的 `dict`/`list`/`tuple`/`set`
- 上下文中禁止包含可调用对象或以 `"__"` 开头的键
- 允许的过滤器包括 `default`、`length`、`upper`、`lower`、`title`、`capitalize`、`replace`、`trim`、`striptags`、`join`、`round`
- 自定义函数需要通过受控的 `environment.globals` 注册,默认仅开放 `insert_image`

### 异步处理

#### 异步工作簿操作

```python
import asyncio
from symphra_excel import AsyncWorkbook

async def process_excel_files():
    # 异步创建工作簿
    workbook = AsyncWorkbook()
    await workbook.create()
    
    # 异步创建工作表
    sheet = await workbook.create_worksheet('异步数据')
    
    # 异步设置数据
    await sheet.set_cell_value('A1', '异步处理的数据')
    
    # 异步保存
    await workbook.save('异步输出.xlsx')

# 运行异步函数
asyncio.run(process_excel_files())
```

#### 批量异步处理

```python
from symphra_excel import AsyncBatchProcessor

async def batch_process_files(file_paths):
    processor = AsyncBatchProcessor(max_workers=8)
    
    def process_workbook(workbook):
        # 处理工作簿的逻辑
        sheet = workbook.create_worksheet('处理结果')
        sheet.set_cell_value('A1', '已处理')
        return workbook
    
    # 异步批量处理
    results = await processor.process_multiple_files(
        file_paths, process_workbook
    )
    
    await processor.close()
    return results
```

### 内存操作

#### 内存工作簿

```python
from symphra_excel import InMemoryWorkbook

# 创建内存工作簿
workbook = InMemoryWorkbook()
sheet = workbook.create_worksheet('内存数据')

# 设置数据
sheet.set_cell_value('A1', '内存中的数据')

# 转换为字节数据
file_data = workbook.to_bytes()

# 从字节数据加载
loaded_workbook = InMemoryWorkbook.from_bytes(file_data)
```

#### 模板内存工作簿

```python
from symphra_excel import InMemoryTemplateWorkbook

# 从模板创建内存工作簿
template_workbook = InMemoryTemplateWorkbook('template.xlsx')

# 渲染模板
context = {'title': '报告标题'}
workbook = template_workbook.render(context)

# 获取字节数据
data = workbook.to_bytes()
```

#### 内存优化工作簿

```python
from symphra_excel import MemoryOptimizedWorkbook

# 创建内存优化工作簿
workbook = MemoryOptimizedWorkbook()

# 使用流式处理大数据
workbook.create_sheet_with_streaming(
    '大数据表',
    data_iterator=large_data_iterator
)

# 清理资源
workbook.cleanup()
```

### 图片处理

#### 插入图片

```python
from symphra_excel import ImageProcessor
from symphra_excel.images.image_processor import CellImageOptions

# 创建图片处理器(可选,用于预处理图片)
processor = ImageProcessor()

# 插入图片到工作表(支持本地路径/字节流)
sheet.insert_image('logo.png', 'A1', width=120, height=60)

# 使用单元格尺寸自适应
sheet.insert_image_with_size('logo.png', 'B1', cell_width=80, cell_height=40)
```

#### 批量插入图片

```python
# 准备图片信息
images_info = [
    {'image': 'image1.png', 'cell': 'A1', 'width': 80},
    {'image': 'image2.jpg', 'cell': 'B1'},
    {'image': 'image3.png', 'cell': 'C1', 'options': CellImageOptions(margin=4)}
]

# 批量插入
sheet.insert_images_batch(images_info)
```

### 性能优化

#### 内存管理

```python
from symphra_excel import MemoryManager, MemoryStrategy

# 创建内存管理器
memory_manager = MemoryManager(
    strategy=MemoryStrategy.BATCHED
)

# 注册对象
memory_manager.register_object(workbook, 'my_workbook')

# 优化内存
memory_manager.optimize_memory()

# 获取内存使用统计
stats = memory_manager.get_memory_stats()
```

#### 大数据处理

```python
from symphra_excel import LargeDataProcessor

# 创建大数据处理器
processor = LargeDataProcessor()

# 导出大数据集
processor.export_large_dataset(
    data_iterator=large_data_iterator,
    output_path='large_dataset.xlsx',
    batch_size=1000,
    memory_strategy=MemoryStrategy.STREAMING
)

# 转换文件格式
processor.convert_file_format(
    input_path='data.csv',
    output_path='data.xlsx',
    input_format='csv',
    output_format='xlsx'
)
```

## 最佳实践

### 1. 内存管理

- 对于大文件处理,使用流式处理策略
- 及时清理不再使用的对象
- 使用内存管理器监控内存使用情况

### 2. 性能优化

- 批量操作比单个操作更高效
- 使用异步处理提高并发性能
- 选择合适的内存策略

### 3. 错误处理

```python
from symphra_excel import ValidationError, MemoryError

try:
    workbook = Workbook.load('large_file.xlsx')
except ValidationError as e:
    print(f'文件验证错误: {e}')
except MemoryError as e:
    print(f'内存错误: {e}')
except Exception as e:
    print(f'其他错误: {e}')
```

### 4. 资源管理

```python
# 使用上下文管理器
with InMemoryWorkbook() as workbook:
    # 处理工作簿
    sheet = workbook.create_worksheet('Test')
    sheet.set_cell_value('A1', 'Test Data')
    data = workbook.to_bytes()
# 自动清理资源

# 异步资源清理
async with AsyncWorkbook() as workbook:
    await workbook.create()
    # 异步操作...
```

## 贡献指南

欢迎贡献代码!请遵循以下步骤:

1. Fork 项目仓库
2. 创建特性分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 创建 Pull Request

### 开发环境设置

```bash
# 克隆项目
git clone https://github.com/yourusername/symphra-excel.git

# 进入项目目录
cd symphra-excel

# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate  # Windows

# 安装依赖
pip install -e .

# 运行测试
pytest tests/
```

## 许可证

本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。

## 支持

如果你有任何问题或建议,请:

- 创建 [GitHub Issue](https://github.com/getaix/symphra-excel/issues)
- 发送邮件到: group@getaix.tech
- 查看 [文档网站](https://getaix.github.io/symphra-excel)

## 更新日志

### 2025-10-30

- 清理整个仓库的导入顺序与代码格式,`isort` / `black` 均通过。
- 强化静态检查,修正图片处理裸捕获异常,并把测试用 `sys.path` 注入逻辑收敛到 `tests/conftest.py`。
- `pytest` 回归 49 项全绿,`ruff check` 通过;`mypy` 在沙箱环境受限暂未执行。

> 历史版本详情待补充至 `CHANGELOG.md`,当前维持 README 内部速记。

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "symphra-excel",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": "getaix <develop@getaix.tech>",
    "keywords": "excel, spreadsheet, xlsx, template, high-performance",
    "author": null,
    "author_email": "getaix <develop@getaix.tech>",
    "download_url": "https://files.pythonhosted.org/packages/13/9a/bbf5d3fc54e51feaa669cd98f9228d97076919aecdd8c17d0d7706955eba/symphra_excel-0.0.1.tar.gz",
    "platform": null,
    "description": "# Symphra Excel Library\n\n\u4e00\u4e2a\u529f\u80fd\u5f3a\u5927\u7684Python Excel\u5904\u7406\u5e93\uff0c\u63d0\u4f9b\u73b0\u4ee3\u5316\u7684API\u63a5\u53e3\u3001\u9ad8\u6027\u80fd\u7684\u6570\u636e\u5904\u7406\u80fd\u529b\u548c\u4e30\u5bcc\u7684\u6837\u5f0f\u652f\u6301\u3002\n\n## \u529f\u80fd\u7279\u6027\n\n- \ud83d\ude80 **\u73b0\u4ee3\u5316API\u8bbe\u8ba1** - \u7b80\u6d01\u76f4\u89c2\u7684\u63a5\u53e3\uff0c\u6613\u4e8e\u4f7f\u7528\n- \ud83c\udfa8 **\u4e30\u5bcc\u7684\u6837\u5f0f\u7cfb\u7edf** - \u652f\u6301\u5b57\u4f53\u3001\u989c\u8272\u3001\u8fb9\u6846\u3001\u5bf9\u9f50\u7b49\u5b8c\u6574\u6837\u5f0f\u8bbe\u7f6e\n- \ud83d\udcca **\u6a21\u677f\u5f15\u64ce** - \u57fa\u4e8eJinja2\u7684\u6a21\u677f\u6e32\u67d3\u7cfb\u7edf\n- \u26a1 **\u5f02\u6b65\u652f\u6301** - \u63d0\u4f9b\u5f02\u6b65API\u63a5\u53e3\uff0c\u652f\u6301\u5e76\u53d1\u5904\u7406\n- \ud83d\udcbe **\u5185\u5b58\u4f18\u5316** - \u9ad8\u6548\u7684\u5185\u5b58\u7ba1\u7406\u548c\u5927\u6570\u636e\u91cf\u5904\u7406\u80fd\u529b\n- \ud83d\uddbc\ufe0f **\u56fe\u7247\u5904\u7406** - \u652f\u6301Excel\u4e2d\u63d2\u5165\u56fe\u7247\u548c\u5d4c\u5165\u5355\u5143\u683c\u529f\u80fd\n- \ud83d\udd27 **\u6269\u5c55\u6027\u5f3a** - \u6a21\u5757\u5316\u8bbe\u8ba1\uff0c\u6613\u4e8e\u6269\u5c55\u548c\u5b9a\u5236\n\n## \u9879\u76ee\u72b6\u6001\uff082025-10-31\uff09\n\n- \u2705 **\u6838\u5fc3\u529f\u80fd\u5b8c\u6574**\uff1a\u540c\u6b65/\u5f02\u6b65 `Workbook` \u4e0e `Worksheet` API \u652f\u6301\u8bfb\u5199\u6a21\u5f0f\u5207\u6362\u3001\u6279\u91cf\u5199\u5165\u3001\u6837\u5f0f\u7ba1\u7406\u3001\u56fe\u7247\u63d2\u5165\n- \u2705 **\u6d4b\u8bd5\u8986\u76d6\u5145\u5206**\uff1a49\u4e2apytest\u6d4b\u8bd5\u7528\u4f8b\u5168\u90e8\u901a\u8fc7\uff0c\u5305\u62ec\u540c\u6b65/\u5f02\u6b65/\u6a21\u677f/\u6837\u5f0f\u7b49\u6838\u5fc3\u529f\u80fd\n- \u2705 **\u7c7b\u578b\u5b89\u5168\u6539\u5584**\uff1amypy\u6838\u5fc3\u5e93\u9519\u8bef\u4ece292\u4e2a\u964d\u81f332\u4e2a\uff08\u51cf\u5c1189%\uff09\uff0c\u5269\u4f59\u9519\u8bef\u4e0d\u5f71\u54cd\u8fd0\u884c\n- \ud83c\udfa8 **\u6a21\u677f\u5f15\u64ce\u53ef\u7528**\uff1a\u57fa\u4e8eJinja2\u6c99\u7bb1\u7684\u6a21\u677f\u7cfb\u7edf\uff0c\u652f\u6301\u5faa\u73af/\u6761\u4ef6/\u56fe\u7247\u5360\u4f4d\uff0c\u53c2\u8003 `examples/03_template_examples.py`\n- \ud83d\ude80 **\u751f\u4ea7\u53ef\u7528**\uff1a\u6838\u5fc3API\u7a33\u5b9a\uff0c\u9002\u5408\u4e2d\u5c0f\u89c4\u6a21Excel\u5904\u7406\u9700\u6c42\n- \ud83d\udcda **\u6587\u6863\u5b8c\u5584\u4e2d**\uff1aAPI\u6587\u6863\u548c\u66f4\u591a\u793a\u4f8b\u6301\u7eed\u8865\u5145\u4e2d\n\n## \u5feb\u901f\u5f00\u59cb\n\n### \u5b89\u88c5\n\n```bash\npip install symphra-excel\n```\n\n### 5\u5206\u949f\u5feb\u901f\u4e0a\u624b\n\n\u6700\u7b80\u5355\u7684Excel\u751f\u6210\u793a\u4f8b\uff08\u5b8c\u6574\u4ee3\u7801\u89c1 [quickstart.py](quickstart.py)\uff09\uff1a\n\n```python\nfrom symphra_excel import Workbook, PredefinedStyles\n\n# 1. \u521b\u5efa\u5de5\u4f5c\u7c3f\u548c\u5de5\u4f5c\u8868\nwb = Workbook()\nsheet = wb.create_worksheet(\"\u9500\u552e\u6570\u636e\")\n\n# 2. \u5199\u5165\u8868\u5934\u5e76\u5e94\u7528\u9884\u5b9a\u4e49\u6837\u5f0f\nheaders = [\"\u4ea7\u54c1\u540d\u79f0\", \"\u9500\u91cf\", \"\u5355\u4ef7\", \"\u603b\u989d\"]\nfor col_idx, header in enumerate(headers):\n    cell_ref = f\"{chr(65 + col_idx)}1\"  # A1, B1, C1, D1\n    sheet.set_cell_value(cell_ref, header)\n    sheet.apply_style(cell_ref, PredefinedStyles.header_style())\n\n# 3. \u5199\u5165\u6570\u636e\ndata = [\n    [\"iPhone 15\", 100, 5999, 599900],\n    [\"MacBook Pro\", 50, 12999, 649950],\n    [\"AirPods Pro\", 200, 1999, 399800],\n]\nfor row_idx, row_data in enumerate(data, start=2):\n    for col_idx, value in enumerate(row_data):\n        cell_ref = f\"{chr(65 + col_idx)}{row_idx}\"\n        sheet.set_cell_value(cell_ref, value)\n\n# 4. \u4fdd\u5b58\u6587\u4ef6\nwb.save(\"\u9500\u552e\u62a5\u8868.xlsx\")\n```\n\n\u8fd0\u884c\u4ee5\u4e0a\u4ee3\u7801\u5c06\u751f\u6210\u4e00\u4e2a\u5305\u542b\u6837\u5f0f\u7684\u4e13\u4e1aExcel\u62a5\u8868\uff01\n\n## \u8be6\u7ec6\u6587\u6863\n\n### \u6838\u5fc3\u6a21\u5757\n\n#### \u5de5\u4f5c\u7c3f\u548c\u5de5\u4f5c\u8868\u64cd\u4f5c\n\n```python\nfrom symphra_excel import Workbook\n\n# \u521b\u5efa\u5de5\u4f5c\u7c3f\nworkbook = Workbook()\n\n# \u521b\u5efa\u5de5\u4f5c\u8868\nsheet1 = workbook.create_worksheet('\u6570\u636e\u88681')\nsheet2 = workbook.create_worksheet('\u6570\u636e\u88682')\n\n# \u83b7\u53d6\u5de5\u4f5c\u8868\nsheet = workbook.get_worksheet('\u6570\u636e\u88681')\n\n# \u5220\u9664\u5de5\u4f5c\u8868\nworkbook.delete_worksheet('\u6570\u636e\u88682')\n\n# \u4fdd\u5b58\u5de5\u4f5c\u7c3f\nworkbook.save('\u8f93\u51fa\u6587\u4ef6.xlsx')\n\n# \u4fdd\u5b58\u5230\u5185\u5b58\nfile_data = workbook.save_to_memory()\n```\n\n#### \u6027\u80fd\u6a21\u5f0f\n\n```python\nfrom symphra_excel import Workbook\n\n# \u53ea\u8bfb\u8bbf\u95ee\u5927\u6587\u4ef6\uff08\u4e0d\u4f1a\u5199\u56de\u539f\u6587\u4ef6\uff09\nreadonly_wb = Workbook(\"report.xlsx\", mode=\"read_only\")\nvalue = readonly_wb.get_worksheet(\"Sheet1\").get_cell_value(\"A1\")\n\n# \u5199\u5165\u6d41\u5f0f\u5bfc\u51fa\uff0c\u6309\u884c\u8ffd\u52a0\u6570\u636e\nstream_wb = Workbook(mode=\"write_only\")\nstream_sheet = stream_wb.create_worksheet(\"Stream\")\nstream_sheet.append_row([\"\u59d3\u540d\", \"\u5206\u6570\"])\nstream_sheet.append_rows([[\"\u5f20\u4e09\", 90], [\"\u674e\u56db\", 85]])\nstream_wb.save(\"stream_output.xlsx\")\n```\n\n#### \u5355\u5143\u683c\u64cd\u4f5c\n\n```python\n# \u8bbe\u7f6e\u5355\u5143\u683c\u503c\nsheet.set_cell_value('A1', 'Hello World')\nsheet.set_cell_value('B1', 123.45)\nsheet.set_cell_value('C1', '=A1+B1')  # \u516c\u5f0f\n\n# \u83b7\u53d6\u5355\u5143\u683c\u503c\nvalue = sheet.get_cell_value('A1')\n\n# \u6279\u91cf\u8bbe\u7f6e\u8303\u56f4\u503c\ndata = [\n    ['\u59d3\u540d', '\u5e74\u9f84', '\u57ce\u5e02'],\n    ['\u5f20\u4e09', 25, '\u5317\u4eac'],\n    ['\u674e\u56db', 30, '\u4e0a\u6d77']\n]\nsheet.set_range_values('A1:C3', data)\n\n# \u83b7\u53d6\u8303\u56f4\u503c\nrange_values = sheet.get_range_values('A1:C3')\n```\n\n#### \u884c\u5217\u64cd\u4f5c\n\n```python\n# \u63d2\u5165\u884c\nsheet.insert_rows(2, 3)  # \u5728\u7b2c2\u884c\u63d2\u51653\u884c\n\n# \u5220\u9664\u884c\nsheet.delete_rows(2, 3)  # \u4ece\u7b2c2\u884c\u5f00\u59cb\u5220\u96643\u884c\n\n# \u63d2\u5165\u5217\nsheet.insert_columns(2, 2)  # \u5728\u7b2c2\u5217\u63d2\u51652\u5217\n\n# \u5220\u9664\u5217\nsheet.delete_columns(2, 2)  # \u4ece\u7b2c2\u5217\u5f00\u59cb\u5220\u96642\u5217\n```\n\n### \u6837\u5f0f\u7cfb\u7edf\n\n#### \u521b\u5efa\u81ea\u5b9a\u4e49\u6837\u5f0f\n\n```python\nfrom symphra_excel import CellStyle, Color\n\n# \u521b\u5efa\u6837\u5f0f\nstyle = CellStyle()\n\n# \u8bbe\u7f6e\u5b57\u4f53\nstyle.set_font(\n    name='\u5fae\u8f6f\u96c5\u9ed1',\n    size=12,\n    bold=True,\n    italic=False,\n    color=Color.WHITE\n)\n\n# \u8bbe\u7f6e\u80cc\u666f\u989c\u8272\nstyle.set_background_color(Color.DARK_BLUE)\n\n# \u8bbe\u7f6e\u8fb9\u6846\nstyle.set_border(\n    left=True, right=True, top=True, bottom=True,\n    left_color=Color.BLACK,\n    right_color=Color.BLACK,\n    top_color=Color.BLACK,\n    bottom_color=Color.BLACK\n)\n\n# \u8bbe\u7f6e\u5bf9\u9f50\u65b9\u5f0f\nstyle.set_alignment(horizontal='center', vertical='center')\n\n# \u8bbe\u7f6e\u6570\u5b57\u683c\u5f0f\nstyle.set_number_format('0.00')\n\n# \u5e94\u7528\u6837\u5f0f\u5230\u5355\u5143\u683c\nsheet.set_cell_style('A1', style)\n```\n\n#### \u4f7f\u7528\u9884\u5b9a\u4e49\u6837\u5f0f\n\n```python\nfrom symphra_excel import PredefinedStyles\n\n# \u8868\u5934\u6837\u5f0f\nheader_style = PredefinedStyles.header_style()\nsheet.set_cell_style('A1', header_style)\n\n# \u6807\u9898\u6837\u5f0f\ntitle_style = PredefinedStyles.title_style()\nsheet.set_cell_style('A1', title_style)\n\n# \u9ad8\u4eae\u6837\u5f0f\nhighlight_style = PredefinedStyles.highlight_style()\nsheet.set_cell_style('A2', highlight_style)\n\n# \u8d27\u5e01\u6837\u5f0f\ncurrency_style = PredefinedStyles.currency_style()\nsheet.set_cell_style('B2', currency_style)\n```\n\n#### \u989c\u8272\u7cfb\u7edf\n\n```python\nfrom symphra_excel import Color, PredefinedStyles\n\n# \u4f7f\u7528\u9884\u5b9a\u4e49\u989c\u8272\nred = Color.RED\nblue = Color.BLUE\ngreen = Color.GREEN\n\n# \u4f7f\u7528\u5341\u516d\u8fdb\u5236\u989c\u8272\nhex_color = Color.from_hex('#FF6B35')\n\n# \u4f7f\u7528RGB\u989c\u8272\nrgb_color = Color.from_rgb(255, 107, 53)\n\n# \u4f7f\u7528\u4e3b\u9898\u989c\u8272\nprimary_color = PredefinedStyles.get_theme_color('primary')\nsecondary_color = PredefinedStyles.get_theme_color('secondary')\n```\n\n### \u6a21\u677f\u5f15\u64ce\n\n#### \u57fa\u672c\u6a21\u677f\u4f7f\u7528\n\n```python\nfrom symphra_excel import TemplateWorkbook\n\n# \u52a0\u8f7d\u6a21\u677f\ntemplate = TemplateWorkbook.load_template('report_template.xlsx')\n\n# \u51c6\u5907\u6570\u636e\ncontext = {\n    'title': '\u6708\u5ea6\u9500\u552e\u62a5\u544a',\n    'date': '2024\u5e741\u6708',\n    'total_sales': 150000,\n    'products': [\n        {'name': '\u4ea7\u54c1A', 'sales': 50000},\n        {'name': '\u4ea7\u54c1B', 'sales': 75000},\n        {'name': '\u4ea7\u54c1C', 'sales': 25000}\n    ]\n}\n\n# \u6e32\u67d3\u6a21\u677f\nworkbook = template.render(context)\n\n# \u4fdd\u5b58\u7ed3\u679c\nworkbook.save('\u751f\u6210\u7684\u62a5\u544a.xlsx')\n```\n\n#### \u6a21\u677f\u8bed\u6cd5\n\n\u652f\u6301Jinja2\u6a21\u677f\u8bed\u6cd5\uff1a\n\n```excel\n{{ title }}                    # \u7b80\u5355\u53d8\u91cf\n{{ date.strftime('%Y-%m') }}   # \u65e5\u671f\u683c\u5f0f\u5316\n{% for product in products %}    # \u5faa\u73af\n{{ product.name }}\n{{ product.sales }}\n{% endfor %}\n\n{{ total_sales | number_format }}  # \u6570\u5b57\u683c\u5f0f\u5316\n{{ title | upper }}                # \u6587\u672c\u8f6c\u6362\n```\n\n#### \u5faa\u73af\u4e0e\u6761\u4ef6\u5757\u8bbe\u8ba1\n\n\u5728\u6a21\u677f\u4e2d\uff0c\u5faa\u73af/\u6761\u4ef6\u63a7\u5236\u8bed\u53e5\u5e94\u72ec\u7acb\u5360\u4e00\u6574\u884c\uff0c\u540e\u7eed\u884c\u7528\u4e8e\u653e\u7f6e\u5b9e\u9645\u5355\u5143\u683c\u5185\u5bb9\u3002\u4f8b\u5982\uff1a\n\n```excel\n{% for row in items %}\n{{ row.name }}\t{{ row.amount }}\n{% endfor %}\n\n{% if show_summary %}\n\u6c47\u603b\t{{ summary }}\n{% endif %}\n```\n\n\u6e32\u67d3\u65f6\u4f1a\u81ea\u52a8\u5c55\u5f00\u5faa\u73af\u5e76\u4fdd\u7559\u5355\u5143\u683c\u683c\u5f0f\uff1b\u6761\u4ef6\u5757\u5728\u5e03\u5c14\u8868\u8fbe\u5f0f\u4e3a `False` \u65f6\u5c06\u88ab\u6574\u4f53\u79fb\u9664\u3002\n\n#### \u6a21\u677f\u56fe\u7247\u5360\u4f4d\u7b26\n\n\u6a21\u677f\u5355\u5143\u683c\u53ef\u4f7f\u7528 `insert_image` \u5360\u4f4d\u7b26\u5ef6\u8fdf\u63d2\u56fe\uff1a\n\n```excel\n{{ insert_image(logo_path, width=120, height=60, maintain_aspect_ratio=True) }}\n```\n\n\u6e32\u67d3\u540e\u5360\u4f4d\u7b26\u6240\u5728\u5355\u5143\u683c\u503c\u4f1a\u88ab\u6e05\u7a7a\uff0c\u56fe\u7247\u6839\u636e\u53c2\u6570\u63d2\u5165\u3002\n\n#### \u4e0a\u4e0b\u6587\u5b89\u5168\u7ea6\u675f\n\n- \u4ec5\u5141\u8bb8\u4f20\u5165 `str`\u3001`int`\u3001`float`\u3001`bool`\u3001`None` \u4ee5\u53ca\u7531\u8fd9\u4e9b\u503c\u7ec4\u6210\u7684 `dict`/`list`/`tuple`/`set`\n- \u4e0a\u4e0b\u6587\u4e2d\u7981\u6b62\u5305\u542b\u53ef\u8c03\u7528\u5bf9\u8c61\u6216\u4ee5 `\"__\"` \u5f00\u5934\u7684\u952e\n- \u5141\u8bb8\u7684\u8fc7\u6ee4\u5668\u5305\u62ec `default`\u3001`length`\u3001`upper`\u3001`lower`\u3001`title`\u3001`capitalize`\u3001`replace`\u3001`trim`\u3001`striptags`\u3001`join`\u3001`round`\n- \u81ea\u5b9a\u4e49\u51fd\u6570\u9700\u8981\u901a\u8fc7\u53d7\u63a7\u7684 `environment.globals` \u6ce8\u518c\uff0c\u9ed8\u8ba4\u4ec5\u5f00\u653e `insert_image`\n\n### \u5f02\u6b65\u5904\u7406\n\n#### \u5f02\u6b65\u5de5\u4f5c\u7c3f\u64cd\u4f5c\n\n```python\nimport asyncio\nfrom symphra_excel import AsyncWorkbook\n\nasync def process_excel_files():\n    # \u5f02\u6b65\u521b\u5efa\u5de5\u4f5c\u7c3f\n    workbook = AsyncWorkbook()\n    await workbook.create()\n    \n    # \u5f02\u6b65\u521b\u5efa\u5de5\u4f5c\u8868\n    sheet = await workbook.create_worksheet('\u5f02\u6b65\u6570\u636e')\n    \n    # \u5f02\u6b65\u8bbe\u7f6e\u6570\u636e\n    await sheet.set_cell_value('A1', '\u5f02\u6b65\u5904\u7406\u7684\u6570\u636e')\n    \n    # \u5f02\u6b65\u4fdd\u5b58\n    await workbook.save('\u5f02\u6b65\u8f93\u51fa.xlsx')\n\n# \u8fd0\u884c\u5f02\u6b65\u51fd\u6570\nasyncio.run(process_excel_files())\n```\n\n#### \u6279\u91cf\u5f02\u6b65\u5904\u7406\n\n```python\nfrom symphra_excel import AsyncBatchProcessor\n\nasync def batch_process_files(file_paths):\n    processor = AsyncBatchProcessor(max_workers=8)\n    \n    def process_workbook(workbook):\n        # \u5904\u7406\u5de5\u4f5c\u7c3f\u7684\u903b\u8f91\n        sheet = workbook.create_worksheet('\u5904\u7406\u7ed3\u679c')\n        sheet.set_cell_value('A1', '\u5df2\u5904\u7406')\n        return workbook\n    \n    # \u5f02\u6b65\u6279\u91cf\u5904\u7406\n    results = await processor.process_multiple_files(\n        file_paths, process_workbook\n    )\n    \n    await processor.close()\n    return results\n```\n\n### \u5185\u5b58\u64cd\u4f5c\n\n#### \u5185\u5b58\u5de5\u4f5c\u7c3f\n\n```python\nfrom symphra_excel import InMemoryWorkbook\n\n# \u521b\u5efa\u5185\u5b58\u5de5\u4f5c\u7c3f\nworkbook = InMemoryWorkbook()\nsheet = workbook.create_worksheet('\u5185\u5b58\u6570\u636e')\n\n# \u8bbe\u7f6e\u6570\u636e\nsheet.set_cell_value('A1', '\u5185\u5b58\u4e2d\u7684\u6570\u636e')\n\n# \u8f6c\u6362\u4e3a\u5b57\u8282\u6570\u636e\nfile_data = workbook.to_bytes()\n\n# \u4ece\u5b57\u8282\u6570\u636e\u52a0\u8f7d\nloaded_workbook = InMemoryWorkbook.from_bytes(file_data)\n```\n\n#### \u6a21\u677f\u5185\u5b58\u5de5\u4f5c\u7c3f\n\n```python\nfrom symphra_excel import InMemoryTemplateWorkbook\n\n# \u4ece\u6a21\u677f\u521b\u5efa\u5185\u5b58\u5de5\u4f5c\u7c3f\ntemplate_workbook = InMemoryTemplateWorkbook('template.xlsx')\n\n# \u6e32\u67d3\u6a21\u677f\ncontext = {'title': '\u62a5\u544a\u6807\u9898'}\nworkbook = template_workbook.render(context)\n\n# \u83b7\u53d6\u5b57\u8282\u6570\u636e\ndata = workbook.to_bytes()\n```\n\n#### \u5185\u5b58\u4f18\u5316\u5de5\u4f5c\u7c3f\n\n```python\nfrom symphra_excel import MemoryOptimizedWorkbook\n\n# \u521b\u5efa\u5185\u5b58\u4f18\u5316\u5de5\u4f5c\u7c3f\nworkbook = MemoryOptimizedWorkbook()\n\n# \u4f7f\u7528\u6d41\u5f0f\u5904\u7406\u5927\u6570\u636e\nworkbook.create_sheet_with_streaming(\n    '\u5927\u6570\u636e\u8868',\n    data_iterator=large_data_iterator\n)\n\n# \u6e05\u7406\u8d44\u6e90\nworkbook.cleanup()\n```\n\n### \u56fe\u7247\u5904\u7406\n\n#### \u63d2\u5165\u56fe\u7247\n\n```python\nfrom symphra_excel import ImageProcessor\nfrom symphra_excel.images.image_processor import CellImageOptions\n\n# \u521b\u5efa\u56fe\u7247\u5904\u7406\u5668\uff08\u53ef\u9009\uff0c\u7528\u4e8e\u9884\u5904\u7406\u56fe\u7247\uff09\nprocessor = ImageProcessor()\n\n# \u63d2\u5165\u56fe\u7247\u5230\u5de5\u4f5c\u8868\uff08\u652f\u6301\u672c\u5730\u8def\u5f84/\u5b57\u8282\u6d41\uff09\nsheet.insert_image('logo.png', 'A1', width=120, height=60)\n\n# \u4f7f\u7528\u5355\u5143\u683c\u5c3a\u5bf8\u81ea\u9002\u5e94\nsheet.insert_image_with_size('logo.png', 'B1', cell_width=80, cell_height=40)\n```\n\n#### \u6279\u91cf\u63d2\u5165\u56fe\u7247\n\n```python\n# \u51c6\u5907\u56fe\u7247\u4fe1\u606f\nimages_info = [\n    {'image': 'image1.png', 'cell': 'A1', 'width': 80},\n    {'image': 'image2.jpg', 'cell': 'B1'},\n    {'image': 'image3.png', 'cell': 'C1', 'options': CellImageOptions(margin=4)}\n]\n\n# \u6279\u91cf\u63d2\u5165\nsheet.insert_images_batch(images_info)\n```\n\n### \u6027\u80fd\u4f18\u5316\n\n#### \u5185\u5b58\u7ba1\u7406\n\n```python\nfrom symphra_excel import MemoryManager, MemoryStrategy\n\n# \u521b\u5efa\u5185\u5b58\u7ba1\u7406\u5668\nmemory_manager = MemoryManager(\n    strategy=MemoryStrategy.BATCHED\n)\n\n# \u6ce8\u518c\u5bf9\u8c61\nmemory_manager.register_object(workbook, 'my_workbook')\n\n# \u4f18\u5316\u5185\u5b58\nmemory_manager.optimize_memory()\n\n# \u83b7\u53d6\u5185\u5b58\u4f7f\u7528\u7edf\u8ba1\nstats = memory_manager.get_memory_stats()\n```\n\n#### \u5927\u6570\u636e\u5904\u7406\n\n```python\nfrom symphra_excel import LargeDataProcessor\n\n# \u521b\u5efa\u5927\u6570\u636e\u5904\u7406\u5668\nprocessor = LargeDataProcessor()\n\n# \u5bfc\u51fa\u5927\u6570\u636e\u96c6\nprocessor.export_large_dataset(\n    data_iterator=large_data_iterator,\n    output_path='large_dataset.xlsx',\n    batch_size=1000,\n    memory_strategy=MemoryStrategy.STREAMING\n)\n\n# \u8f6c\u6362\u6587\u4ef6\u683c\u5f0f\nprocessor.convert_file_format(\n    input_path='data.csv',\n    output_path='data.xlsx',\n    input_format='csv',\n    output_format='xlsx'\n)\n```\n\n## \u6700\u4f73\u5b9e\u8df5\n\n### 1. \u5185\u5b58\u7ba1\u7406\n\n- \u5bf9\u4e8e\u5927\u6587\u4ef6\u5904\u7406\uff0c\u4f7f\u7528\u6d41\u5f0f\u5904\u7406\u7b56\u7565\n- \u53ca\u65f6\u6e05\u7406\u4e0d\u518d\u4f7f\u7528\u7684\u5bf9\u8c61\n- \u4f7f\u7528\u5185\u5b58\u7ba1\u7406\u5668\u76d1\u63a7\u5185\u5b58\u4f7f\u7528\u60c5\u51b5\n\n### 2. \u6027\u80fd\u4f18\u5316\n\n- \u6279\u91cf\u64cd\u4f5c\u6bd4\u5355\u4e2a\u64cd\u4f5c\u66f4\u9ad8\u6548\n- \u4f7f\u7528\u5f02\u6b65\u5904\u7406\u63d0\u9ad8\u5e76\u53d1\u6027\u80fd\n- \u9009\u62e9\u5408\u9002\u7684\u5185\u5b58\u7b56\u7565\n\n### 3. \u9519\u8bef\u5904\u7406\n\n```python\nfrom symphra_excel import ValidationError, MemoryError\n\ntry:\n    workbook = Workbook.load('large_file.xlsx')\nexcept ValidationError as e:\n    print(f'\u6587\u4ef6\u9a8c\u8bc1\u9519\u8bef: {e}')\nexcept MemoryError as e:\n    print(f'\u5185\u5b58\u9519\u8bef: {e}')\nexcept Exception as e:\n    print(f'\u5176\u4ed6\u9519\u8bef: {e}')\n```\n\n### 4. \u8d44\u6e90\u7ba1\u7406\n\n```python\n# \u4f7f\u7528\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\nwith InMemoryWorkbook() as workbook:\n    # \u5904\u7406\u5de5\u4f5c\u7c3f\n    sheet = workbook.create_worksheet('Test')\n    sheet.set_cell_value('A1', 'Test Data')\n    data = workbook.to_bytes()\n# \u81ea\u52a8\u6e05\u7406\u8d44\u6e90\n\n# \u5f02\u6b65\u8d44\u6e90\u6e05\u7406\nasync with AsyncWorkbook() as workbook:\n    await workbook.create()\n    # \u5f02\u6b65\u64cd\u4f5c...\n```\n\n## \u8d21\u732e\u6307\u5357\n\n\u6b22\u8fce\u8d21\u732e\u4ee3\u7801\uff01\u8bf7\u9075\u5faa\u4ee5\u4e0b\u6b65\u9aa4\uff1a\n\n1. Fork \u9879\u76ee\u4ed3\u5e93\n2. \u521b\u5efa\u7279\u6027\u5206\u652f (`git checkout -b feature/amazing-feature`)\n3. \u63d0\u4ea4\u66f4\u6539 (`git commit -m 'Add some amazing feature'`)\n4. \u63a8\u9001\u5230\u5206\u652f (`git push origin feature/amazing-feature`)\n5. \u521b\u5efa Pull Request\n\n### \u5f00\u53d1\u73af\u5883\u8bbe\u7f6e\n\n```bash\n# \u514b\u9686\u9879\u76ee\ngit clone https://github.com/yourusername/symphra-excel.git\n\n# \u8fdb\u5165\u9879\u76ee\u76ee\u5f55\ncd symphra-excel\n\n# \u521b\u5efa\u865a\u62df\u73af\u5883\npython -m venv venv\nsource venv/bin/activate  # Linux/Mac\n# venv\\Scripts\\activate  # Windows\n\n# \u5b89\u88c5\u4f9d\u8d56\npip install -e .\n\n# \u8fd0\u884c\u6d4b\u8bd5\npytest tests/\n```\n\n## \u8bb8\u53ef\u8bc1\n\n\u672c\u9879\u76ee\u91c7\u7528 MIT \u8bb8\u53ef\u8bc1 - \u67e5\u770b [LICENSE](LICENSE) \u6587\u4ef6\u4e86\u89e3\u8be6\u60c5\u3002\n\n## \u652f\u6301\n\n\u5982\u679c\u4f60\u6709\u4efb\u4f55\u95ee\u9898\u6216\u5efa\u8bae\uff0c\u8bf7\uff1a\n\n- \u521b\u5efa [GitHub Issue](https://github.com/getaix/symphra-excel/issues)\n- \u53d1\u9001\u90ae\u4ef6\u5230: group@getaix.tech\n- \u67e5\u770b [\u6587\u6863\u7f51\u7ad9](https://getaix.github.io/symphra-excel)\n\n## \u66f4\u65b0\u65e5\u5fd7\n\n### 2025-10-30\n\n- \u6e05\u7406\u6574\u4e2a\u4ed3\u5e93\u7684\u5bfc\u5165\u987a\u5e8f\u4e0e\u4ee3\u7801\u683c\u5f0f\uff0c`isort` / `black` \u5747\u901a\u8fc7\u3002\n- \u5f3a\u5316\u9759\u6001\u68c0\u67e5\uff0c\u4fee\u6b63\u56fe\u7247\u5904\u7406\u88f8\u6355\u83b7\u5f02\u5e38\uff0c\u5e76\u628a\u6d4b\u8bd5\u7528 `sys.path` \u6ce8\u5165\u903b\u8f91\u6536\u655b\u5230 `tests/conftest.py`\u3002\n- `pytest` \u56de\u5f52 49 \u9879\u5168\u7eff\uff0c`ruff check` \u901a\u8fc7\uff1b`mypy` \u5728\u6c99\u7bb1\u73af\u5883\u53d7\u9650\u6682\u672a\u6267\u884c\u3002\n\n> \u5386\u53f2\u7248\u672c\u8be6\u60c5\u5f85\u8865\u5145\u81f3 `CHANGELOG.md`\uff0c\u5f53\u524d\u7ef4\u6301 README \u5185\u90e8\u901f\u8bb0\u3002\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "High-performance Excel processing library for Python 3.11+",
    "version": "0.0.1",
    "project_urls": {
        "Bug Tracker": "https://github.com/getaix/symphra-excel/issues",
        "Documentation": "https://getaix.github.io/symphra-excel",
        "Homepage": "https://github.com/getaix/symphra-excel",
        "Repository": "https://github.com/getaix/symphra-excel.git"
    },
    "split_keywords": [
        "excel",
        " spreadsheet",
        " xlsx",
        " template",
        " high-performance"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e712649052a38765e92ddcbedc8eb0cd4dce356849385998a4f3fe47bdf8ec0f",
                "md5": "cf07ddbbf2a4bc575534d011304541a7",
                "sha256": "8cb5ac1b16c8e4f440bfe0db35ce176b8856a9b7d02912e43a38f0f2f267d2d7"
            },
            "downloads": -1,
            "filename": "symphra_excel-0.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "cf07ddbbf2a4bc575534d011304541a7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 89822,
            "upload_time": "2025-11-02T06:59:28",
            "upload_time_iso_8601": "2025-11-02T06:59:28.296463Z",
            "url": "https://files.pythonhosted.org/packages/e7/12/649052a38765e92ddcbedc8eb0cd4dce356849385998a4f3fe47bdf8ec0f/symphra_excel-0.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "139abbf5d3fc54e51feaa669cd98f9228d97076919aecdd8c17d0d7706955eba",
                "md5": "ea5dfa50aa3a9044da5ef6e44ad679c8",
                "sha256": "c09a560a00b594d34b89305052eed51e649d51bc7fce09e0b4d6d7897095cee1"
            },
            "downloads": -1,
            "filename": "symphra_excel-0.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ea5dfa50aa3a9044da5ef6e44ad679c8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 115004,
            "upload_time": "2025-11-02T06:59:30",
            "upload_time_iso_8601": "2025-11-02T06:59:30.119409Z",
            "url": "https://files.pythonhosted.org/packages/13/9a/bbf5d3fc54e51feaa669cd98f9228d97076919aecdd8c17d0d7706955eba/symphra_excel-0.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-02 06:59:30",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "getaix",
    "github_project": "symphra-excel",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "symphra-excel"
}
        
Elapsed time: 1.20998s