Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/workbook/_writer.py: 15%

118 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1# Copyright (c) 2010-2022 openpyxl 

2 

3"""Write the workbook global settings to the archive.""" 

4 

5from copy import copy 

6 

7from openpyxl.utils import absolute_coordinate, quote_sheetname 

8from openpyxl.xml.constants import ( 

9 ARC_APP, 

10 ARC_CORE, 

11 ARC_WORKBOOK, 

12 PKG_REL_NS, 

13 CUSTOMUI_NS, 

14 ARC_ROOT_RELS, 

15) 

16from openpyxl.xml.functions import tostring, fromstring 

17 

18from openpyxl.packaging.relationship import Relationship, RelationshipList 

19from openpyxl.workbook.defined_name import DefinedName 

20from openpyxl.workbook.external_reference import ExternalReference 

21from openpyxl.packaging.workbook import ChildSheet, WorkbookPackage, PivotCache 

22from openpyxl.workbook.properties import WorkbookProperties 

23from openpyxl.utils.datetime import CALENDAR_MAC_1904 

24 

25 

26def get_active_sheet(wb): 

27 """ 

28 Return the index of the active sheet. 

29 If the sheet set to active is hidden return the next visible sheet or None 

30 """ 

31 visible_sheets = [idx for idx, sheet in enumerate(wb._sheets) if sheet.sheet_state == "visible"] 

32 if not visible_sheets: 

33 raise IndexError("At least one sheet must be visible") 

34 

35 idx = wb._active_sheet_index 

36 sheet = wb.active 

37 if sheet and sheet.sheet_state == "visible": 

38 return idx 

39 

40 for idx in visible_sheets[idx:]: 

41 wb.active = idx 

42 return idx 

43 

44 return None 

45 

46 

47class WorkbookWriter: 

48 

49 def __init__(self, wb): 

50 self.wb = wb 

51 self.rels = RelationshipList() 

52 self.package = WorkbookPackage() 

53 self.package.workbookProtection = wb.security 

54 self.package.calcPr = wb.calculation 

55 

56 

57 def write_properties(self): 

58 

59 props = WorkbookProperties() # needs a mapping to the workbook for preservation 

60 if self.wb.code_name is not None: 

61 props.codeName = self.wb.code_name 

62 if self.wb.excel_base_date == CALENDAR_MAC_1904: 

63 props.date1904 = True 

64 self.package.workbookPr = props 

65 

66 

67 def write_worksheets(self): 

68 for idx, sheet in enumerate(self.wb._sheets, 1): 

69 sheet_node = ChildSheet(name=sheet.title, sheetId=idx, id="rId{0}".format(idx)) 

70 rel = Relationship(type=sheet._rel_type, Target=sheet.path) 

71 self.rels.append(rel) 

72 

73 if not sheet.sheet_state == 'visible': 

74 if len(self.wb._sheets) == 1: 

75 raise ValueError("The only worksheet of a workbook cannot be hidden") 

76 sheet_node.state = sheet.sheet_state 

77 self.package.sheets.append(sheet_node) 

78 

79 

80 def write_refs(self): 

81 for link in self.wb._external_links: 

82 # need to match a counter with a workbook's relations 

83 rId = len(self.wb.rels) + 1 

84 rel = Relationship(type=link._rel_type, Target=link.path) 

85 self.rels.append(rel) 

86 ext = ExternalReference(id=rel.id) 

87 self.package.externalReferences.append(ext) 

88 

89 

90 def write_names(self): 

91 defined_names = copy(self.wb.defined_names) 

92 

93 # Defined names -> autoFilter 

94 for idx, sheet in enumerate(self.wb.worksheets): 

95 auto_filter = sheet.auto_filter.ref 

96 

97 if auto_filter: 

98 name = DefinedName(name='_FilterDatabase', localSheetId=idx, hidden=True) 

99 name.value = u"{0}!{1}".format(quote_sheetname(sheet.title), 

100 absolute_coordinate(auto_filter) 

101 ) 

102 defined_names.append(name) 

103 

104 # print titles 

105 if sheet.print_titles: 

106 name = DefinedName(name="Print_Titles", localSheetId=idx) 

107 name.value = ",".join([u"{0}!{1}".format(quote_sheetname(sheet.title), r) 

108 for r in sheet.print_titles.split(",")]) 

109 defined_names.append(name) 

110 

111 # print areas 

112 if sheet.print_area: 

113 name = DefinedName(name="Print_Area", localSheetId=idx) 

114 name.value = ",".join([u"{0}!{1}".format(quote_sheetname(sheet.title), r) 

115 for r in sheet.print_area]) 

116 defined_names.append(name) 

117 

118 self.package.definedNames = defined_names 

119 

120 

121 def write_pivots(self): 

122 pivot_caches = set() 

123 for pivot in self.wb._pivots: 

124 if pivot.cache not in pivot_caches: 

125 pivot_caches.add(pivot.cache) 

126 c = PivotCache(cacheId=pivot.cacheId) 

127 self.package.pivotCaches.append(c) 

128 rel = Relationship(Type=pivot.cache.rel_type, Target=pivot.cache.path) 

129 self.rels.append(rel) 

130 c.id = rel.id 

131 #self.wb._pivots = [] # reset 

132 

133 

134 def write_views(self): 

135 active = get_active_sheet(self.wb) 

136 if self.wb.views: 

137 self.wb.views[0].activeTab = active 

138 self.package.bookViews = self.wb.views 

139 

140 

141 def write(self): 

142 """Write the core workbook xml.""" 

143 

144 self.write_properties() 

145 self.write_worksheets() 

146 self.write_names() 

147 self.write_pivots() 

148 self.write_views() 

149 self.write_refs() 

150 

151 return tostring(self.package.to_tree()) 

152 

153 

154 def write_rels(self): 

155 """Write the workbook relationships xml.""" 

156 

157 styles = Relationship(type='styles', Target='styles.xml') 

158 self.rels.append(styles) 

159 

160 theme = Relationship(type='theme', Target='theme/theme1.xml') 

161 self.rels.append(theme) 

162 

163 if self.wb.vba_archive: 

164 vba = Relationship(type='', Target='vbaProject.bin') 

165 vba.Type ='http://schemas.microsoft.com/office/2006/relationships/vbaProject' 

166 self.rels.append(vba) 

167 

168 return tostring(self.rels.to_tree()) 

169 

170 

171 def write_root_rels(self): 

172 """Write the package relationships""" 

173 

174 rels = RelationshipList() 

175 

176 rel = Relationship(type="officeDocument", Target=ARC_WORKBOOK) 

177 rels.append(rel) 

178 rel = Relationship(Type=f"{PKG_REL_NS}/metadata/core-properties", Target=ARC_CORE) 

179 rels.append(rel) 

180 

181 rel = Relationship(type="extended-properties", Target=ARC_APP) 

182 rels.append(rel) 

183 

184 if self.wb.vba_archive is not None: 

185 # See if there was a customUI relation and reuse it 

186 xml = fromstring(self.wb.vba_archive.read(ARC_ROOT_RELS)) 

187 root_rels = RelationshipList.from_tree(xml) 

188 for rel in root_rels.find(CUSTOMUI_NS): 

189 rels.append(rel) 

190 

191 return tostring(rels.to_tree())