1
- from typing import TYPE_CHECKING , Dict , List , Optional
1
+ from typing import List
2
2
3
3
import numpy as np
4
4
8
8
from pandas .io .excel ._base import ExcelWriter , _BaseExcelReader
9
9
from pandas .io .excel ._util import _validate_freeze_panes
10
10
11
- if TYPE_CHECKING :
12
- from openpyxl .descriptors .serialisable import Serialisable
13
-
14
11
15
12
class _OpenpyxlWriter (ExcelWriter ):
16
13
engine = "openpyxl"
@@ -25,22 +22,53 @@ def __init__(self, path, engine=None, mode="w", **engine_kwargs):
25
22
if self .mode == "a" : # Load from existing workbook
26
23
from openpyxl import load_workbook
27
24
28
- self .book = load_workbook (self .path )
25
+ book = load_workbook (self .path )
26
+ self .book = book
29
27
else :
30
28
# Create workbook object with default optimized_write=True.
31
29
self .book = Workbook ()
32
30
33
31
if self .book .worksheets :
34
- self .book .remove (self .book .worksheets [0 ])
32
+ try :
33
+ self .book .remove (self .book .worksheets [0 ])
34
+ except AttributeError :
35
+
36
+ # compat - for openpyxl <= 2.4
37
+ self .book .remove_sheet (self .book .worksheets [0 ])
35
38
36
39
def save (self ):
37
40
"""
38
41
Save workbook to disk.
39
42
"""
40
- self .book .save (self .path )
43
+ return self .book .save (self .path )
44
+
45
+ @classmethod
46
+ def _convert_to_style (cls , style_dict ):
47
+ """
48
+ Converts a style_dict to an openpyxl style object.
49
+
50
+ Parameters
51
+ ----------
52
+ style_dict : style dictionary to convert
53
+ """
54
+ from openpyxl .style import Style
55
+
56
+ xls_style = Style ()
57
+ for key , value in style_dict .items ():
58
+ for nk , nv in value .items ():
59
+ if key == "borders" :
60
+ (
61
+ xls_style .borders .__getattribute__ (nk ).__setattr__ (
62
+ "border_style" , nv
63
+ )
64
+ )
65
+ else :
66
+ xls_style .__getattribute__ (key ).__setattr__ (nk , nv )
67
+
68
+ return xls_style
41
69
42
70
@classmethod
43
- def _convert_to_style_kwargs (cls , style_dict : dict ) -> Dict [ str , "Serialisable" ] :
71
+ def _convert_to_style_kwargs (cls , style_dict ) :
44
72
"""
45
73
Convert a style_dict to a set of kwargs suitable for initializing
46
74
or updating-on-copy an openpyxl v2 style object.
@@ -65,7 +93,7 @@ def _convert_to_style_kwargs(cls, style_dict: dict) -> Dict[str, "Serialisable"]
65
93
"""
66
94
_style_key_map = {"borders" : "border" }
67
95
68
- style_kwargs : Dict [ str , Serialisable ] = {}
96
+ style_kwargs = {}
69
97
for k , v in style_dict .items ():
70
98
if k in _style_key_map :
71
99
k = _style_key_map [k ]
@@ -376,7 +404,7 @@ def write_cells(
376
404
# Write the frame cells using openpyxl.
377
405
sheet_name = self ._get_sheet_name (sheet_name )
378
406
379
- _style_cache : Dict [ str , Dict [ str , Serialisable ]] = {}
407
+ _style_cache = {}
380
408
381
409
if sheet_name in self .sheets :
382
410
wks = self .sheets [sheet_name ]
@@ -398,7 +426,7 @@ def write_cells(
398
426
if fmt :
399
427
xcell .number_format = fmt
400
428
401
- style_kwargs : Optional [ Dict [ str , Serialisable ]] = {}
429
+ style_kwargs = {}
402
430
if cell .style :
403
431
key = str (cell .style )
404
432
style_kwargs = _style_cache .get (key )
@@ -487,17 +515,16 @@ def get_sheet_by_index(self, index: int):
487
515
488
516
def _convert_cell (self , cell , convert_float : bool ) -> Scalar :
489
517
490
- from openpyxl .cell .cell import TYPE_BOOL , TYPE_ERROR , TYPE_NUMERIC
491
-
518
+ # TODO: replace with openpyxl constants
492
519
if cell .is_date :
493
520
return cell .value
494
- elif cell .data_type == TYPE_ERROR :
521
+ elif cell .data_type == "e" :
495
522
return np .nan
496
- elif cell .data_type == TYPE_BOOL :
523
+ elif cell .data_type == "b" :
497
524
return bool (cell .value )
498
525
elif cell .value is None :
499
526
return "" # compat with xlrd
500
- elif cell .data_type == TYPE_NUMERIC :
527
+ elif cell .data_type == "n" :
501
528
# GH5394
502
529
if convert_float :
503
530
val = int (cell .value )
0 commit comments