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
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# Copyright (c) 2010-2022 openpyxl
3"""Write the workbook global settings to the archive."""
5from copy import copy
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
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
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")
35 idx = wb._active_sheet_index
36 sheet = wb.active
37 if sheet and sheet.sheet_state == "visible":
38 return idx
40 for idx in visible_sheets[idx:]:
41 wb.active = idx
42 return idx
44 return None
47class WorkbookWriter:
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
57 def write_properties(self):
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
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)
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)
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)
90 def write_names(self):
91 defined_names = copy(self.wb.defined_names)
93 # Defined names -> autoFilter
94 for idx, sheet in enumerate(self.wb.worksheets):
95 auto_filter = sheet.auto_filter.ref
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)
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)
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)
118 self.package.definedNames = defined_names
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
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
141 def write(self):
142 """Write the core workbook xml."""
144 self.write_properties()
145 self.write_worksheets()
146 self.write_names()
147 self.write_pivots()
148 self.write_views()
149 self.write_refs()
151 return tostring(self.package.to_tree())
154 def write_rels(self):
155 """Write the workbook relationships xml."""
157 styles = Relationship(type='styles', Target='styles.xml')
158 self.rels.append(styles)
160 theme = Relationship(type='theme', Target='theme/theme1.xml')
161 self.rels.append(theme)
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)
168 return tostring(self.rels.to_tree())
171 def write_root_rels(self):
172 """Write the package relationships"""
174 rels = RelationshipList()
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)
181 rel = Relationship(type="extended-properties", Target=ARC_APP)
182 rels.append(rel)
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)
191 return tostring(rels.to_tree())