Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Copyright (c) 2010-2020 openpyxl 

2 

3 

4"""Write worksheets to xml representations in an optimized way""" 

5 

6from inspect import isgenerator 

7 

8from openpyxl.cell import Cell, WriteOnlyCell 

9from openpyxl.workbook.child import _WorkbookChild 

10from .worksheet import Worksheet 

11from openpyxl.utils.exceptions import WorkbookAlreadySaved 

12 

13from ._writer import WorksheetWriter 

14 

15 

16class WriteOnlyWorksheet(_WorkbookChild): 

17 """ 

18 Streaming worksheet. Optimised to reduce memory by writing rows just in 

19 time. 

20 Cells can be styled and have comments Styles for rows and columns 

21 must be applied before writing cells 

22 """ 

23 

24 __saved = False 

25 _writer = None 

26 _rows = None 

27 _rel_type = Worksheet._rel_type 

28 _path = Worksheet._path 

29 mime_type = Worksheet.mime_type 

30 

31 # copy methods from Standard worksheet 

32 _add_row = Worksheet._add_row 

33 _add_column = Worksheet._add_column 

34 add_chart = Worksheet.add_chart 

35 add_image = Worksheet.add_image 

36 add_table = Worksheet.add_table 

37 print_titles = Worksheet.print_titles 

38 print_title_cols = Worksheet.print_title_cols 

39 print_title_rows = Worksheet.print_title_rows 

40 freeze_panes = Worksheet.freeze_panes 

41 print_area = Worksheet.print_area 

42 sheet_view = Worksheet.sheet_view 

43 _setup = Worksheet._setup 

44 

45 def __init__(self, parent, title): 

46 super(WriteOnlyWorksheet, self).__init__(parent, title) 

47 self._max_col = 0 

48 self._max_row = 0 

49 self._setup() 

50 

51 @property 

52 def closed(self): 

53 return self.__saved 

54 

55 

56 def _write_rows(self): 

57 """ 

58 Send rows to the writer's stream 

59 """ 

60 try: 

61 xf = self._writer.xf.send(True) 

62 except StopIteration: 

63 self._already_saved() 

64 

65 with xf.element("sheetData"): 

66 row_idx = 1 

67 try: 

68 while True: 

69 row = (yield) 

70 row = self._values_to_row(row, row_idx) 

71 self._writer.write_row(xf, row, row_idx) 

72 row_idx += 1 

73 except GeneratorExit: 

74 pass 

75 

76 self._writer.xf.send(None) 

77 

78 

79 def _get_writer(self): 

80 if self._writer is None: 

81 self._writer = WorksheetWriter(self) 

82 self._writer.write_top() 

83 

84 

85 def close(self): 

86 if self.__saved: 

87 self._already_saved() 

88 

89 self._get_writer() 

90 

91 if self._rows is None: 

92 self._writer.write_rows() 

93 else: 

94 self._rows.close() 

95 

96 self._writer.write_tail() 

97 

98 self._writer.close() 

99 self.__saved = True 

100 

101 

102 def append(self, row): 

103 """ 

104 :param row: iterable containing values to append 

105 :type row: iterable 

106 """ 

107 

108 if (not isgenerator(row) and 

109 not isinstance(row, (list, tuple, range)) 

110 ): 

111 self._invalid_row(row) 

112 

113 self._get_writer() 

114 

115 if self._rows is None: 

116 self._rows = self._write_rows() 

117 next(self._rows) 

118 

119 self._rows.send(row) 

120 

121 

122 def _values_to_row(self, values, row_idx): 

123 """ 

124 Convert whatever has been appended into a form suitable for work_rows 

125 """ 

126 cell = WriteOnlyCell(self) 

127 

128 for col_idx, value in enumerate(values, 1): 

129 if value is None: 

130 continue 

131 try: 

132 cell.value = value 

133 except ValueError: 

134 if isinstance(value, Cell): 

135 cell = value 

136 else: 

137 raise ValueError 

138 

139 cell.column = col_idx 

140 cell.row = row_idx 

141 

142 if cell.hyperlink is not None: 

143 cell.hyperlink.ref = cell.coordinate 

144 

145 yield cell 

146 

147 # reset cell if style applied 

148 if cell.has_style or cell.hyperlink: 

149 cell = WriteOnlyCell(self) 

150 

151 

152 def _already_saved(self): 

153 raise WorkbookAlreadySaved('Workbook has already been saved and cannot be modified or saved anymore.') 

154 

155 

156 def _invalid_row(self, iterable): 

157 raise TypeError('Value must be a list, tuple, range or a generator Supplied value is {0}'.format( 

158 type(iterable)) 

159 ) 

160 @property 

161 def tables(self): 

162 return self.tables