2828from pandas .core import config
2929from pandas .io .formats .printing import pprint_thing
3030import pandas .compat as compat
31- import pandas .compat .openpyxl_compat as openpyxl_compat
3231from warnings import warn
3332from distutils .version import LooseVersion
3433from pandas .util ._decorators import Appender , deprecate_kwarg
@@ -185,22 +184,6 @@ def _get_default_writer(ext):
185184
186185
187186def get_writer (engine_name ):
188- if engine_name == 'openpyxl' :
189- try :
190- import openpyxl
191-
192- # with version-less openpyxl engine
193- # make sure we make the intelligent choice for the user
194- if LooseVersion (openpyxl .__version__ ) < '2.0.0' :
195- return _writers ['openpyxl1' ]
196- elif LooseVersion (openpyxl .__version__ ) < '2.2.0' :
197- return _writers ['openpyxl20' ]
198- else :
199- return _writers ['openpyxl22' ]
200- except ImportError :
201- # fall through to normal exception handling below
202- pass
203-
204187 try :
205188 return _writers [engine_name ]
206189 except KeyError :
@@ -828,20 +811,15 @@ def close(self):
828811 return self .save ()
829812
830813
831- class _Openpyxl1Writer (ExcelWriter ):
832- engine = 'openpyxl1 '
814+ class _OpenpyxlWriter (ExcelWriter ):
815+ engine = 'openpyxl '
833816 supported_extensions = ('.xlsx' , '.xlsm' )
834- openpyxl_majorver = 1
835817
836818 def __init__ (self , path , engine = None , ** engine_kwargs ):
837- if not openpyxl_compat .is_compat (major_ver = self .openpyxl_majorver ):
838- raise ValueError ('Installed openpyxl is not supported at this '
839- 'time. Use {majorver}.x.y.'
840- .format (majorver = self .openpyxl_majorver ))
841819 # Use the openpyxl module as the Excel writer.
842820 from openpyxl .workbook import Workbook
843821
844- super (_Openpyxl1Writer , self ).__init__ (path , ** engine_kwargs )
822+ super (_OpenpyxlWriter , self ).__init__ (path , ** engine_kwargs )
845823
846824 # Create workbook object with default optimized_write=True.
847825 self .book = Workbook ()
@@ -861,72 +839,6 @@ def save(self):
861839 """
862840 return self .book .save (self .path )
863841
864- def write_cells (self , cells , sheet_name = None , startrow = 0 , startcol = 0 ,
865- freeze_panes = None ):
866- # Write the frame cells using openpyxl.
867- from openpyxl .cell import get_column_letter
868-
869- sheet_name = self ._get_sheet_name (sheet_name )
870-
871- if sheet_name in self .sheets :
872- wks = self .sheets [sheet_name ]
873- else :
874- wks = self .book .create_sheet ()
875- wks .title = sheet_name
876- self .sheets [sheet_name ] = wks
877-
878- for cell in cells :
879- colletter = get_column_letter (startcol + cell .col + 1 )
880- xcell = wks .cell ("{col}{row}" .format (col = colletter ,
881- row = startrow + cell .row + 1 ))
882- if (isinstance (cell .val , compat .string_types ) and
883- xcell .data_type_for_value (cell .val ) != xcell .TYPE_STRING ):
884- xcell .set_value_explicit (cell .val )
885- else :
886- xcell .value = _conv_value (cell .val )
887- style = None
888- if cell .style :
889- style = self ._convert_to_style (cell .style )
890- for field in style .__fields__ :
891- xcell .style .__setattr__ (field ,
892- style .__getattribute__ (field ))
893-
894- if isinstance (cell .val , datetime ):
895- xcell .style .number_format .format_code = self .datetime_format
896- elif isinstance (cell .val , date ):
897- xcell .style .number_format .format_code = self .date_format
898-
899- if cell .mergestart is not None and cell .mergeend is not None :
900- cletterstart = get_column_letter (startcol + cell .col + 1 )
901- cletterend = get_column_letter (startcol + cell .mergeend + 1 )
902-
903- wks .merge_cells ('{start}{row}:{end}{mergestart}'
904- .format (start = cletterstart ,
905- row = startrow + cell .row + 1 ,
906- end = cletterend ,
907- mergestart = startrow +
908- cell .mergestart + 1 ))
909-
910- # Excel requires that the format of the first cell in a merged
911- # range is repeated in the rest of the merged range.
912- if style :
913- first_row = startrow + cell .row + 1
914- last_row = startrow + cell .mergestart + 1
915- first_col = startcol + cell .col + 1
916- last_col = startcol + cell .mergeend + 1
917-
918- for row in range (first_row , last_row + 1 ):
919- for col in range (first_col , last_col + 1 ):
920- if row == first_row and col == first_col :
921- # Ignore first cell. It is already handled.
922- continue
923- colletter = get_column_letter (col )
924- xcell = wks .cell ("{col}{row}"
925- .format (col = colletter , row = row ))
926- for field in style .__fields__ :
927- xcell .style .__setattr__ (
928- field , style .__getattribute__ (field ))
929-
930842 @classmethod
931843 def _convert_to_style (cls , style_dict ):
932844 """
@@ -948,88 +860,6 @@ def _convert_to_style(cls, style_dict):
948860
949861 return xls_style
950862
951-
952- register_writer (_Openpyxl1Writer )
953-
954-
955- class _OpenpyxlWriter (_Openpyxl1Writer ):
956- engine = 'openpyxl'
957-
958-
959- register_writer (_OpenpyxlWriter )
960-
961-
962- class _Openpyxl20Writer (_Openpyxl1Writer ):
963- """
964- Note: Support for OpenPyxl v2 is currently EXPERIMENTAL (GH7565).
965- """
966- engine = 'openpyxl20'
967- openpyxl_majorver = 2
968-
969- def write_cells (self , cells , sheet_name = None , startrow = 0 , startcol = 0 ,
970- freeze_panes = None ):
971- # Write the frame cells using openpyxl.
972- from openpyxl .cell import get_column_letter
973-
974- sheet_name = self ._get_sheet_name (sheet_name )
975-
976- if sheet_name in self .sheets :
977- wks = self .sheets [sheet_name ]
978- else :
979- wks = self .book .create_sheet ()
980- wks .title = sheet_name
981- self .sheets [sheet_name ] = wks
982-
983- for cell in cells :
984- colletter = get_column_letter (startcol + cell .col + 1 )
985- xcell = wks ["{col}{row}"
986- .format (col = colletter , row = startrow + cell .row + 1 )]
987- xcell .value = _conv_value (cell .val )
988- style_kwargs = {}
989-
990- # Apply format codes before cell.style to allow override
991- if isinstance (cell .val , datetime ):
992- style_kwargs .update (self ._convert_to_style_kwargs ({
993- 'number_format' : {'format_code' : self .datetime_format }}))
994- elif isinstance (cell .val , date ):
995- style_kwargs .update (self ._convert_to_style_kwargs ({
996- 'number_format' : {'format_code' : self .date_format }}))
997-
998- if cell .style :
999- style_kwargs .update (self ._convert_to_style_kwargs (cell .style ))
1000-
1001- if style_kwargs :
1002- xcell .style = xcell .style .copy (** style_kwargs )
1003-
1004- if cell .mergestart is not None and cell .mergeend is not None :
1005- cletterstart = get_column_letter (startcol + cell .col + 1 )
1006- cletterend = get_column_letter (startcol + cell .mergeend + 1 )
1007-
1008- wks .merge_cells ('{start}{row}:{end}{mergestart}'
1009- .format (start = cletterstart ,
1010- row = startrow + cell .row + 1 ,
1011- end = cletterend ,
1012- mergestart = startrow +
1013- cell .mergestart + 1 ))
1014-
1015- # Excel requires that the format of the first cell in a merged
1016- # range is repeated in the rest of the merged range.
1017- if style_kwargs :
1018- first_row = startrow + cell .row + 1
1019- last_row = startrow + cell .mergestart + 1
1020- first_col = startcol + cell .col + 1
1021- last_col = startcol + cell .mergeend + 1
1022-
1023- for row in range (first_row , last_row + 1 ):
1024- for col in range (first_col , last_col + 1 ):
1025- if row == first_row and col == first_col :
1026- # Ignore first cell. It is already handled.
1027- continue
1028- colletter = get_column_letter (col )
1029- xcell = wks ["{col}{row}"
1030- .format (col = colletter , row = row )]
1031- xcell .style = xcell .style .copy (** style_kwargs )
1032-
1033863 @classmethod
1034864 def _convert_to_style_kwargs (cls , style_dict ):
1035865 """
@@ -1341,13 +1171,7 @@ def _convert_to_number_format(cls, number_format_dict):
13411171 -------
13421172 number_format : str
13431173 """
1344- try :
1345- # >= 2.0.0 < 2.1.0
1346- from openpyxl .styles import NumberFormat
1347- return NumberFormat (** number_format_dict )
1348- except :
1349- # >= 2.1.0
1350- return number_format_dict ['format_code' ]
1174+ return number_format_dict ['format_code' ]
13511175
13521176 @classmethod
13531177 def _convert_to_protection (cls , protection_dict ):
@@ -1367,17 +1191,6 @@ def _convert_to_protection(cls, protection_dict):
13671191
13681192 return Protection (** protection_dict )
13691193
1370-
1371- register_writer (_Openpyxl20Writer )
1372-
1373-
1374- class _Openpyxl22Writer (_Openpyxl20Writer ):
1375- """
1376- Note: Support for OpenPyxl v2.2 is currently EXPERIMENTAL (GH7565).
1377- """
1378- engine = 'openpyxl22'
1379- openpyxl_majorver = 2
1380-
13811194 def write_cells (self , cells , sheet_name = None , startrow = 0 , startcol = 0 ,
13821195 freeze_panes = None ):
13831196 # Write the frame cells using openpyxl.
@@ -1443,7 +1256,7 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0,
14431256 setattr (xcell , k , v )
14441257
14451258
1446- register_writer (_Openpyxl22Writer )
1259+ register_writer (_OpenpyxlWriter )
14471260
14481261
14491262class _XlwtWriter (ExcelWriter ):
0 commit comments