5
5
6
6
from pandas .io .excel ._base import ExcelWriter
7
7
8
- # from pandas.io.excel._util import _validate_freeze_panes
8
+ from pandas .io .excel ._util import _validate_freeze_panes
9
9
10
10
from odf .opendocument import OpenDocumentSpreadsheet
11
11
from odf .style import Style , TextProperties , TableCellProperties , ParagraphProperties
12
12
from odf .table import Table , TableRow , TableCell
13
13
from odf .text import P
14
+ from odf .config import ConfigItemSet , ConfigItemMapEntry , ConfigItemMapNamed , ConfigItem , ConfigItemMapIndexed
14
15
15
16
16
17
class _ODSWriter (ExcelWriter ):
@@ -36,11 +37,11 @@ def save(self):
36
37
self .book .spreadsheet .addElement (sheet )
37
38
return self .book .save (self .path )
38
39
39
- def write_cells (
40
- self , cells , sheet_name = None , startrow = 0 , startcol = 0 , freeze_panes = None
41
- ):
40
+ def write_cells (self , cells , sheet_name = None , startrow = 0 , startcol = 0 ,
41
+ freeze_panes = None ):
42
42
# Write the frame cells using odf
43
-
43
+ # assert startrow == 0
44
+ # assert startcol == 0
44
45
sheet_name = self ._get_sheet_name (sheet_name )
45
46
46
47
if sheet_name in self .sheets :
@@ -49,65 +50,69 @@ def write_cells(
49
50
wks = Table (name = sheet_name )
50
51
self .sheets [sheet_name ] = wks
51
52
52
- # if _validate_freeze_panes(freeze_panes):
53
- # wks.set_panes_frozen(True)
54
- # wks.set_horz_split_pos(freeze_panes[0])
55
- # wks.set_vert_split_pos(freeze_panes[1])
56
-
53
+ if _validate_freeze_panes (freeze_panes ):
54
+ self ._create_freeze_panes (sheet_name , freeze_panes )
57
55
58
56
rows = defaultdict (TableRow )
59
57
col_count = defaultdict (int )
60
58
61
59
for cell in sorted (cells , key = lambda cell : (cell .row , cell .col )):
62
- attributes = {}
63
- style_name = self ._process_style (cell .style )
64
- if style_name is not None :
65
- attributes ["stylename" ] = style_name
66
- print (cell .row , cell .col , cell .val , cell .mergestart , cell .mergeend )
67
- if cell .mergestart is not None and cell .mergeend is not None :
68
- attributes ["numberrowsspanned" ] = max (1 , cell .mergestart )
69
- attributes ["numbercolumnsspanned" ] = cell .mergeend
70
60
# fill with empty cells if needed
71
61
for _ in range (cell .col - col_count [cell .row ]):
72
62
rows [cell .row ].addElement (TableCell ())
73
63
col_count [cell .row ] += 1
74
- val , fmt = self ._value_with_fmt (cell .val )
75
- # print("type", type(val), "value", val)
76
- pvalue = value = val
77
- if isinstance (val , bool ):
78
- value = str (val ).lower ()
79
- pvalue = str (val ).upper ()
80
- if isinstance (val , datetime .datetime ):
81
- if val .time ():
82
- value = val .isoformat ()
83
- pvalue = val .strftime ("%c" )
84
- else :
85
- value = val .strftime ("%Y-%m-%d" )
86
- pvalue = val .strftime ("%x" )
87
- tc = TableCell (valuetype = "date" , datevalue = value , attributes = attributes )
88
- elif isinstance (val , datetime .date ):
89
- value = val .strftime ("%Y-%m-%d" )
90
- pvalue = val .strftime ("%x" )
91
- tc = TableCell (valuetype = "date" , datevalue = value , attributes = attributes )
92
- else :
93
- class_to_cell_type = {
94
- str : "string" ,
95
- int : "float" ,
96
- float : "float" ,
97
- bool : "boolean" ,
98
- }
99
- tc = TableCell (
100
- valuetype = class_to_cell_type [type (val )],
101
- value = value ,
102
- attributes = attributes ,
103
- )
64
+
65
+ pvalue , tc = self ._make_table_cell (cell )
104
66
rows [cell .row ].addElement (tc )
105
67
col_count [cell .row ] += 1
106
68
p = P (text = pvalue )
107
69
tc .addElement (p )
70
+
71
+ # add all rows to the sheet
108
72
for row_nr in range (max (rows .keys ()) + 1 ):
109
73
wks .addElement (rows [row_nr ])
110
74
75
+ def _make_table_cell_attributes (self , cell ):
76
+ attributes = {}
77
+ style_name = self ._process_style (cell .style )
78
+ if style_name is not None :
79
+ attributes ["stylename" ] = style_name
80
+ if cell .mergestart is not None and cell .mergeend is not None :
81
+ attributes ["numberrowsspanned" ] = max (1 , cell .mergestart )
82
+ attributes ["numbercolumnsspanned" ] = cell .mergeend
83
+ return attributes
84
+
85
+ def _make_table_cell (self , cell ):
86
+ attributes = self ._make_table_cell_attributes (cell )
87
+ val , fmt = self ._value_with_fmt (cell .val )
88
+ pvalue = value = val
89
+ if isinstance (val , bool ):
90
+ value = str (val ).lower ()
91
+ pvalue = str (val ).upper ()
92
+ if isinstance (val , datetime .datetime ):
93
+ if val .time ():
94
+ value = val .isoformat ()
95
+ pvalue = val .strftime ("%c" )
96
+ else :
97
+ value = val .strftime ("%Y-%m-%d" )
98
+ pvalue = val .strftime ("%x" )
99
+ return pvalue , TableCell (valuetype = "date" , datevalue = value ,
100
+ attributes = attributes )
101
+ elif isinstance (val , datetime .date ):
102
+ value = val .strftime ("%Y-%m-%d" )
103
+ pvalue = val .strftime ("%x" )
104
+ return pvalue , TableCell (valuetype = "date" , datevalue = value ,
105
+ attributes = attributes )
106
+ else :
107
+ class_to_cell_type = {
108
+ str : "string" ,
109
+ int : "float" ,
110
+ float : "float" ,
111
+ bool : "boolean" ,
112
+ }
113
+ return pvalue , TableCell (valuetype = class_to_cell_type [type (val )],
114
+ value = value , attributes = attributes )
115
+
111
116
def _process_style (self , style ):
112
117
if style is None :
113
118
return None
@@ -140,3 +145,38 @@ def _process_style(self, style):
140
145
odf_style .addElement (TableCellProperties (verticalalign = vertical ))
141
146
self .book .styles .addElement (odf_style )
142
147
return name
148
+
149
+ def _create_freeze_panes (self , sheet_name , freeze_panes ):
150
+ config_item_set = ConfigItemSet (name = "ooo:view-settings" )
151
+ self .book .settings .addElement (config_item_set )
152
+
153
+ config_item_map_indexed = ConfigItemMapIndexed (name = "Views" )
154
+ config_item_set .addElement (config_item_map_indexed )
155
+
156
+ config_item_map_entry = ConfigItemMapEntry ()
157
+ config_item_map_indexed .addElement (config_item_map_entry )
158
+
159
+ config_item_map_named = ConfigItemMapNamed (name = "Tables" )
160
+ config_item_map_entry .addElement (config_item_map_named )
161
+
162
+ config_item_map_entry = ConfigItemMapEntry (name = sheet_name )
163
+ config_item_map_named .addElement (config_item_map_entry )
164
+
165
+ config_item_map_entry .addElement (ConfigItem (name = "HorizontalSplitMode" ,
166
+ type = "short" ,
167
+ text = "2" ))
168
+ config_item_map_entry .addElement (ConfigItem (name = "VerticalSplitMode" ,
169
+ type = "short" ,
170
+ text = "2" ))
171
+ config_item_map_entry .addElement (ConfigItem (name = "HorizontalSplitPosition" ,
172
+ type = "int" ,
173
+ text = str (freeze_panes [0 ])))
174
+ config_item_map_entry .addElement (ConfigItem (name = "VerticalSplitPosition" ,
175
+ type = "int" ,
176
+ text = str (freeze_panes [1 ])))
177
+ config_item_map_entry .addElement (ConfigItem (name = "PositionRight" ,
178
+ type = "int" ,
179
+ text = str (freeze_panes [0 ])))
180
+ config_item_map_entry .addElement (ConfigItem (name = "PositionBottom" ,
181
+ type = "int" ,
182
+ text = str (freeze_panes [1 ])))
0 commit comments