-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Added ability to freeze panes from DataFrame.to_excel() (#15160) #15291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -1390,7 +1390,8 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None, | |||
def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', | ||||
float_format=None, columns=None, header=True, index=True, | ||||
index_label=None, startrow=0, startcol=0, engine=None, | ||||
merge_cells=True, encoding=None, inf_rep='inf', verbose=True): | ||||
merge_cells=True, encoding=None, inf_rep='inf', verbose=True, | ||||
freeze_panes=None): | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add Line 1021 in 9ddba8d
|
||||
from pandas.io.excel import ExcelWriter | ||||
need_save = False | ||||
if encoding is None: | ||||
|
@@ -1406,12 +1407,26 @@ def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', | |||
index_label=index_label, | ||||
merge_cells=merge_cells, | ||||
inf_rep=inf_rep) | ||||
|
||||
formatted_cells = formatter.get_formatted_cells() | ||||
freeze_panes = self._validate_freeze_panes(freeze_panes) | ||||
excel_writer.write_cells(formatted_cells, sheet_name, | ||||
startrow=startrow, startcol=startcol) | ||||
startrow=startrow, startcol=startcol, | ||||
freeze_panes=freeze_panes) | ||||
if need_save: | ||||
excel_writer.save() | ||||
|
||||
def _validate_freeze_panes(self, freeze_panes): | ||||
if freeze_panes is not None: | ||||
if ( | ||||
len(freeze_panes) == 2 and | ||||
all(isinstance(item, int) for item in freeze_panes) | ||||
): | ||||
return freeze_panes | ||||
|
||||
raise ValueError("freeze_panes must be of form (row, column)" | ||||
" where row and column are integers") | ||||
|
||||
def to_stata(self, fname, convert_dates=None, write_index=True, | ||||
encoding="latin-1", byteorder=None, time_stamp=None, | ||||
data_label=None, variable_labels=None): | ||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1033,7 +1033,7 @@ def __setstate__(self, state): | |
# I/O Methods | ||
|
||
_shared_docs['to_excel'] = """ | ||
Write %(klass)s to a excel sheet | ||
Write %(klass)s to an excel sheet | ||
%(versionadded_to_excel)s | ||
Parameters | ||
---------- | ||
|
@@ -1072,6 +1072,11 @@ def __setstate__(self, state): | |
inf_rep : string, default 'inf' | ||
Representation for infinity (there is no native representation for | ||
infinity in Excel) | ||
freeze_panes : tuple of integer (length 2), default None | ||
Specifies the bottommost row and rightmost column that | ||
is to be frozen | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add a versionadded tag here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this start at zero or one? |
||
.. versionadded:: 0.20.0 | ||
Notes | ||
----- | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -693,7 +693,8 @@ def engine(self): | |
pass | ||
|
||
@abc.abstractmethod | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
""" | ||
Write given formated cells into Excel an excel sheet | ||
|
@@ -705,6 +706,8 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | |
Name of Excel sheet, if None, then use self.cur_sheet | ||
startrow: upper left cell row to dump data frame | ||
startcol: upper left cell column to dump data frame | ||
freeze_panes: integer tuple of length 2 | ||
contains the bottom-most row and right-most column to freeze | ||
""" | ||
pass | ||
|
||
|
@@ -804,7 +807,8 @@ def save(self): | |
""" | ||
return self.book.save(self.path) | ||
|
||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
# Write the frame cells using openpyxl. | ||
from openpyxl.cell import get_column_letter | ||
|
||
|
@@ -904,7 +908,8 @@ class _Openpyxl20Writer(_Openpyxl1Writer): | |
engine = 'openpyxl20' | ||
openpyxl_majorver = 2 | ||
|
||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
# Write the frame cells using openpyxl. | ||
from openpyxl.cell import get_column_letter | ||
|
||
|
@@ -1311,7 +1316,8 @@ class _Openpyxl22Writer(_Openpyxl20Writer): | |
engine = 'openpyxl22' | ||
openpyxl_majorver = 2 | ||
|
||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
# Write the frame cells using openpyxl. | ||
sheet_name = self._get_sheet_name(sheet_name) | ||
|
||
|
@@ -1324,6 +1330,10 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | |
wks.title = sheet_name | ||
self.sheets[sheet_name] = wks | ||
|
||
if freeze_panes is not None: | ||
wks.freeze_panes = wks.cell(row=freeze_panes[0] + 1, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. vaidate that its a len 2 tuples |
||
column=freeze_panes[1] + 1) | ||
|
||
for cell in cells: | ||
xcell = wks.cell( | ||
row=startrow + cell.row + 1, | ||
|
@@ -1396,7 +1406,8 @@ def save(self): | |
""" | ||
return self.book.save(self.path) | ||
|
||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
# Write the frame cells using xlwt. | ||
|
||
sheet_name = self._get_sheet_name(sheet_name) | ||
|
@@ -1407,6 +1418,11 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | |
wks = self.book.add_sheet(sheet_name) | ||
self.sheets[sheet_name] = wks | ||
|
||
if freeze_panes is not None: | ||
wks.set_panes_frozen(True) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
wks.set_horz_split_pos(freeze_panes[0]) | ||
wks.set_vert_split_pos(freeze_panes[1]) | ||
|
||
style_dict = {} | ||
|
||
for cell in cells: | ||
|
@@ -1518,11 +1534,12 @@ def save(self): | |
""" | ||
Save workbook to disk. | ||
""" | ||
|
||
return self.book.close() | ||
|
||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | ||
def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0, | ||
freeze_panes=None): | ||
# Write the frame cells using xlsxwriter. | ||
|
||
sheet_name = self._get_sheet_name(sheet_name) | ||
|
||
if sheet_name in self.sheets: | ||
|
@@ -1533,6 +1550,9 @@ def write_cells(self, cells, sheet_name=None, startrow=0, startcol=0): | |
|
||
style_dict = {} | ||
|
||
if freeze_panes is not None: | ||
wks.freeze_panes(*(freeze_panes)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same (you may want to make a general validation for this somewhere) |
||
|
||
for cell in cells: | ||
val = _conv_value(cell.val) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line will not be formatted nicely in the html docs (it needs two spaces at the start to have it indented in the list)