123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- from __future__ import absolute_import
- # Copyright (c) 2010-2019 openpyxl
- """Write worksheets to xml representations in an optimized way"""
- from inspect import isgenerator
- from openpyxl.cell import Cell, WriteOnlyCell
- from openpyxl.workbook.child import _WorkbookChild
- from .worksheet import Worksheet
- from openpyxl.utils.exceptions import WorkbookAlreadySaved
- from ._writer import WorksheetWriter
- class WriteOnlyWorksheet(_WorkbookChild):
- """
- Streaming worksheet. Optimised to reduce memory by writing rows just in
- time.
- Cells can be styled and have comments Styles for rows and columns
- must be applied before writing cells
- """
- __saved = False
- _writer = None
- _rows = None
- _rel_type = Worksheet._rel_type
- _path = Worksheet._path
- mime_type = Worksheet.mime_type
- def __init__(self, parent, title):
- super(WriteOnlyWorksheet, self).__init__(parent, title)
- self._max_col = 0
- self._max_row = 0
- # Methods from Worksheet
- self._add_row = Worksheet._add_row.__get__(self)
- self._add_column = Worksheet._add_column.__get__(self)
- self.add_chart = Worksheet.add_chart.__get__(self)
- self.add_image = Worksheet.add_image.__get__(self)
- self.add_table = Worksheet.add_table.__get__(self)
- setup = Worksheet._setup.__get__(self)
- setup()
- self.print_titles = Worksheet.print_titles.__get__(self)
- self.sheet_view = Worksheet.sheet_view.__get__(self)
- @property
- def freeze_panes(self):
- return Worksheet.freeze_panes.__get__(self)
- @freeze_panes.setter
- def freeze_panes(self, value):
- Worksheet.freeze_panes.__set__(self, value)
- @property
- def print_title_cols(self):
- return Worksheet.print_title_cols.__get__(self)
- @print_title_cols.setter
- def print_title_cols(self, value):
- Worksheet.print_title_cols.__set__(self, value)
- @property
- def print_title_rows(self):
- return Worksheet.print_title_rows.__get__(self)
- @print_title_rows.setter
- def print_title_rows(self, value):
- Worksheet.print_title_rows.__set__(self, value)
- @property
- def print_area(self):
- return Worksheet.print_area.__get__(self)
- @print_area.setter
- def print_area(self, value):
- Worksheet.print_area.__set__(self, value)
- @property
- def closed(self):
- return self.__saved
- def _write_rows(self):
- """
- Send rows to the writer's stream
- """
- try:
- xf = self._writer.xf.send(True)
- except StopIteration:
- self._already_saved()
- with xf.element("sheetData"):
- row_idx = 1
- try:
- while True:
- row = (yield)
- row = self._values_to_row(row, row_idx)
- self._writer.write_row(xf, row, row_idx)
- row_idx += 1
- except GeneratorExit:
- pass
- self._writer.xf.send(None)
- def _get_writer(self):
- if self._writer is None:
- self._writer = WorksheetWriter(self)
- self._writer.write_top()
- def close(self):
- if self.__saved:
- self._already_saved()
- self._get_writer()
- if self._rows is None:
- self._writer.write_rows()
- else:
- self._rows.close()
- self._writer.write_tail()
- self._writer.close()
- self.__saved = True
- def append(self, row):
- """
- :param row: iterable containing values to append
- :type row: iterable
- """
- if (not isgenerator(row) and
- not isinstance(row, (list, tuple, range))
- ):
- self._invalid_row(row)
- self._get_writer()
- if self._rows is None:
- self._rows = self._write_rows()
- next(self._rows)
- self._rows.send(row)
- def _values_to_row(self, values, row_idx):
- """
- Convert whatever has been appended into a form suitable for work_rows
- """
- cell = WriteOnlyCell(self)
- for col_idx, value in enumerate(values, 1):
- if value is None:
- continue
- try:
- cell.value = value
- except ValueError:
- if isinstance(value, Cell):
- cell = value
- else:
- raise ValueError
- cell.column = col_idx
- cell.row = row_idx
- if cell.hyperlink is not None:
- cell.hyperlink.ref = cell.coordinate
- yield cell
- # reset cell if style applied
- if cell.has_style or cell.hyperlink:
- cell = WriteOnlyCell(self)
- def _already_saved(self):
- raise WorkbookAlreadySaved('Workbook has already been saved and cannot be modified or saved anymore.')
- def _invalid_row(self, iterable):
- raise TypeError('Value must be a list, tuple, range or a generator Supplied value is {0}'.format(
- type(iterable))
- )
|