Files
redmine-reporter/redmine_reporter/formatters/csv.py
Кокос Артем Николаевич 222d31730e feat(xlsx): make Excel export production-grade
- Add merge cells for project/version groups.
- Add numeric Hours column and human-readable Spent Time.
- Add version/project/grand totals.
- Apply auto-width, freeze panes, auto-filter and styling.
- Respect --no-time: keep columns empty, skip totals.
- Pass no_time flag through formatter factory to all file formatters.
- Add tests for XLSX features and --no-time behavior.

Closes #38
2026-06-29 14:41:37 +07:00

46 lines
1.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import csv
import io
from typing import List
from ..types import ReportRow
from .base import Formatter
class CSVFormatter(Formatter):
"""Форматтер для экспорта в CSV.
Использует полные значения project/version (а не display-значения с пустыми
ячейками для групп). Каждая строка CSV самодостаточна — это корректно для
табличного формата (#31). Файл сохраняется в UTF-8 с BOM (utf-8-sig) для
корректного отображения кириллицы в Microsoft Excel (#26).
"""
def __init__(self, no_time: bool = False, **_kwargs):
super().__init__()
self.no_time = no_time
def format(self, rows: List[ReportRow]) -> str:
output = io.StringIO()
writer = csv.writer(output, dialect="excel")
headers = ["Project", "Version", "Issue ID", "Subject", "Status"]
if not self.no_time:
headers.append("Spent Time")
writer.writerow(headers)
for r in rows:
data = [
r["project"],
r["version"],
r["issue_id"],
r["subject"],
r["status_ru"],
]
if not self.no_time:
data.append(r["time_text"])
writer.writerow(data)
return output.getvalue()
def save(self, rows: List[ReportRow], output_path: str) -> None:
content = self.format(rows)
with open(output_path, "w", encoding="utf-8-sig", newline="") as f:
f.write(content)