IndexError: At least one sheet must be visible
Question:
def multiple_dfs(sheet, row=2):
writer = pd.ExcelWriter("testing.xlsx", engine='openpyxl')
f1 = {
'user': ['Bob', 'Jane', 'Alice'],
'income': [40000, 50000, 42000],
}
f2 = {
'amount': ['Chest', 'Bras', 'Braa'],
'income': [40000, 50000, 42000]
}
frames = [f1, f2]
for f in frames:
try:
wb = load_workbook("testing.xlsx")
ws = wb.get_sheet_by_name("aaa")
writer.wb = wb
writer.sheets = dict((ws.title, ws) for ws in wb.worksheets)
row = ws.max_row + 2
except:
pass
df = pd.DataFrame(f)
df.to_excel(writer, sheet, startrow=row, index=False)
writer.save()
# writer.close()
multiple_dfs('aaa')
I got this error, but I can’t fix it. I adapt this short representation of what is happening in my code, but it is hard to see where is the real problem. Here is the
Traceback (most recent call last):
File "create_and_update_xlsx_sheets.py", line 144, in <module>
create_and_update_worksheets()
File "create_and_update_xlsx_sheets.py", line 140, in create_and_update_worksheets
writer.save()
File "/home/jeremie/.virtualenvs/NHL/lib/python3.5/site-packages/pandas/io/excel.py", line 824, in save
return self.book.save(self.path)
...
File "/home/jeremie/.virtualenvs/NHL/lib/python3.5/site-packages/openpyxl/writer/workbook.py", line 61, in get_active_sheet
raise IndexError("At least one sheet must be visible")
IndexError: At least one sheet must be visible
How could I fix that issue?
P.S. Be aware that error is displayed half the time.
Answers:
It seems like what you want to do is just write each DataFrame to the same sheet (appending it below the last), so I think you can write this as:
start_row = 1
for df in frames: # assuming they're already DataFrames
df.to_excel(writer, sheet, startrow=start_row, index=False)
start_row += len(df) + 1 # add a row for the column header?
writer.save() # we only need to save to disk at the very end!
Alternatively, if you don’t need to load a workbook, you can merely use xlsxwriter instead of openpyxl; it hasn’t this problem. You can also create a workbook with the regular
from openpyxl import Workbook
#...
wb= Workbook()
ws=wb.active
with pd.ExcelWriter(output_filepath, engine="openpyxl") as writer:
writer.book=wb
writer.sheets = dict((ws.title, ws) for ws in wb.worksheets)
#useful code
df.to_excel(writer, sheet, ...)
writer.save()
now you can work with both pandas.to_excel and the interesting methods of openpyxl that are not translated into it (that’s not my hack; found it here but can’t find where)
working perfectly fine on pandas 1.1.5 and openpyxl 3.0.5.
Change your pandas and openpyxl library on above mentioned version.
In Pandas 1.3.5 I needed to assign the engine as xlsxwriter.
with pd.ExcelWriter('path-to-.xlsx-file',engine='xlsxwriter') as writer:
df.to_excel(writer, 'spreadsheet-name')
https://pandas.pydata.org/docs/dev/reference/api/pandas.ExcelWriter.html
Same error, IndexError: At least one sheet must be visible
, consistently reproduced when a writer is created, then saved, without having written anything. Example:
writer = pd.ExcelWriter(file_name, engine='openpyxl')
writer.save()
Stepping through the code, the workbook doesn’t contain any sheets at time of writing, visible or otherwise, despite having sheets before calling save
.
Granted, hard to match that to your code, but a clue to you or next dev coming across same error.
You should be able to do wb.save("filename.xlsx")
rather than use excelwriter at all.
writer.save
is an excelwriter method while openpyxl has its own save method that takes a filename after you opened a workbook.
You can also use the wb.sheetnames
and wb.create_sheet
to navigate sheets.
from openpyxl import Workbook, load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
wb = load_workbook(PATH + "yourfile.xlsx")
#writer = pd.ExcelWriter(PATH + "yourfile.xlsx", engine='openpyxl')
wb2 = []
if "MySheetName" in wb.sheetnames:
wb2 = wb["MySheetName"]
else:
wb2 = wb.create_sheet("MySheetName",-1) #Auto add at the end
#wb2 is now the active sheet for wb
for r in dataframe_to_rows(df, index=True, header=True):
wb2.append(r)
wb.save(PATH + "yourfile.xlsx")
Hope it helps
def multiple_dfs(sheet, row=2):
writer = pd.ExcelWriter("testing.xlsx", engine='openpyxl')
f1 = {
'user': ['Bob', 'Jane', 'Alice'],
'income': [40000, 50000, 42000],
}
f2 = {
'amount': ['Chest', 'Bras', 'Braa'],
'income': [40000, 50000, 42000]
}
frames = [f1, f2]
for f in frames:
try:
wb = load_workbook("testing.xlsx")
ws = wb.get_sheet_by_name("aaa")
writer.wb = wb
writer.sheets = dict((ws.title, ws) for ws in wb.worksheets)
row = ws.max_row + 2
except:
pass
df = pd.DataFrame(f)
df.to_excel(writer, sheet, startrow=row, index=False)
writer.save()
# writer.close()
multiple_dfs('aaa')
I got this error, but I can’t fix it. I adapt this short representation of what is happening in my code, but it is hard to see where is the real problem. Here is the
Traceback (most recent call last):
File "create_and_update_xlsx_sheets.py", line 144, in <module>
create_and_update_worksheets()
File "create_and_update_xlsx_sheets.py", line 140, in create_and_update_worksheets
writer.save()
File "/home/jeremie/.virtualenvs/NHL/lib/python3.5/site-packages/pandas/io/excel.py", line 824, in save
return self.book.save(self.path)
...
File "/home/jeremie/.virtualenvs/NHL/lib/python3.5/site-packages/openpyxl/writer/workbook.py", line 61, in get_active_sheet
raise IndexError("At least one sheet must be visible")
IndexError: At least one sheet must be visible
How could I fix that issue?
P.S. Be aware that error is displayed half the time.
It seems like what you want to do is just write each DataFrame to the same sheet (appending it below the last), so I think you can write this as:
start_row = 1
for df in frames: # assuming they're already DataFrames
df.to_excel(writer, sheet, startrow=start_row, index=False)
start_row += len(df) + 1 # add a row for the column header?
writer.save() # we only need to save to disk at the very end!
Alternatively, if you don’t need to load a workbook, you can merely use xlsxwriter instead of openpyxl; it hasn’t this problem. You can also create a workbook with the regular
from openpyxl import Workbook
#...
wb= Workbook()
ws=wb.active
with pd.ExcelWriter(output_filepath, engine="openpyxl") as writer:
writer.book=wb
writer.sheets = dict((ws.title, ws) for ws in wb.worksheets)
#useful code
df.to_excel(writer, sheet, ...)
writer.save()
now you can work with both pandas.to_excel and the interesting methods of openpyxl that are not translated into it (that’s not my hack; found it here but can’t find where)
working perfectly fine on pandas 1.1.5 and openpyxl 3.0.5.
Change your pandas and openpyxl library on above mentioned version.
In Pandas 1.3.5 I needed to assign the engine as xlsxwriter.
with pd.ExcelWriter('path-to-.xlsx-file',engine='xlsxwriter') as writer:
df.to_excel(writer, 'spreadsheet-name')
https://pandas.pydata.org/docs/dev/reference/api/pandas.ExcelWriter.html
Same error, IndexError: At least one sheet must be visible
, consistently reproduced when a writer is created, then saved, without having written anything. Example:
writer = pd.ExcelWriter(file_name, engine='openpyxl')
writer.save()
Stepping through the code, the workbook doesn’t contain any sheets at time of writing, visible or otherwise, despite having sheets before calling save
.
Granted, hard to match that to your code, but a clue to you or next dev coming across same error.
You should be able to do wb.save("filename.xlsx")
rather than use excelwriter at all.
writer.save
is an excelwriter method while openpyxl has its own save method that takes a filename after you opened a workbook.
You can also use the wb.sheetnames
and wb.create_sheet
to navigate sheets.
from openpyxl import Workbook, load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
wb = load_workbook(PATH + "yourfile.xlsx")
#writer = pd.ExcelWriter(PATH + "yourfile.xlsx", engine='openpyxl')
wb2 = []
if "MySheetName" in wb.sheetnames:
wb2 = wb["MySheetName"]
else:
wb2 = wb.create_sheet("MySheetName",-1) #Auto add at the end
#wb2 is now the active sheet for wb
for r in dataframe_to_rows(df, index=True, header=True):
wb2.append(r)
wb.save(PATH + "yourfile.xlsx")
Hope it helps