Column and row dimensions in OpenPyXL are always None - python

Why is openpyxl reading every row and column dimension as None? This is the case regardless of whether the table was created via openpyxl or within Microsoft Excel.
import openpyxl
wb = openpyxl.load_workbook(r'C:\data\MyTable.xlsx')
ws = wb.active
print ws.row_dimensions[1].height
print ws.column_dimensions['A'].width
prints None and None. These aren't hidden columns/rows. They clearly have dimensions when viewed in Excel.
I know that loading the workbook with iterators will prevent the dimension dictionaries from being created, but that results in key errors, and I'm not using iterators here.
Is there an alternative way to determine the width/height of a cell/row/column?
===============SOLUTION=================
Thanks to Charlie, I realized that the following is the best way to get a list of all row heights:
import openpyxl
wb = openpyxl.load_workbook(r'C:\Data\Test.xlsx')
ws = wb.active
rowHeights = [ws.row_dimensions[i+1].height for i in range(ws.max_row)]
rowHeights = [15 if rh is None else rh for rh in rowHeights]

RowDimension and ColumnDimension objects exist only when the defaults are to be overwritten. So ws.row_dimensions[1].height will be always be None until it is assigned a value.
The default values are: {'defaultRowHeight': '15', 'baseColWidth': '10'}

openpyxl: 3.0.4
source code: from openpyxl.worksheet.dimensions import SheetFormatProperties
it shows the {'defaultRowHeight': 15, 'baseColWidth': 8}
# dimensions.py
class SheetFormatProperties(Serialisable):
...
def __init__(self,
baseColWidth=8, # <-----------------
defaultColWidth=None,
defaultRowHeight=15, # <------------
customHeight=None,
zeroHeight=None,
thickTop=None,
thickBottom=None,
outlineLevelRow=None,
outlineLevelCol=None,
):
self.baseColWidth = baseColWidth
self.defaultColWidth = defaultColWidth
self.defaultRowHeight = defaultRowHeight
self.customHeight = customHeight
self.zeroHeight = zeroHeight
...
an example
from openpyxl import load_workbook
from openpyxl.worksheet.dimensions import SheetFormatProperties
from openpyxl.worksheet.worksheet import Worksheet
wb = load_workbook('xxx.xlsx')
for sheet in [wb[sheet_name] for sheet_name in wb.sheetnames]:
sheet: Worksheet
sheet_prop: SheetFormatProperties = sheet.sheet_format
default_width = sheet_prop.baseColWidth
default_height = sheet_prop.defaultRowHeight

Related

Writing data to excel from a formula in python

What I want is with openpyxl to write a value I get form a len() or dups() to an excel cell.
Here are my imports:
import xlwings as xw
Here is the code:
#Load workbook
app = xw.App(visible = False)
wb = xw.Book(FilePath)
RawData_ws = wb.sheets['Raw Data']
Sheet1 = wb.sheets['Sheet 1']
RawData_ws['A1'] = (len(df.index))
Sheet1['B7'] = (len(df.index) - tot_dups))
RawData_ws['A2'] = (len(df.index)) #This one is after removing duplicate values
Tot_dups:
tot_dups = len(df.index)
I want the values of the different len() to show be written in the specific cells.
So, I already found the solution.
Change:
RawData_ws['A1'] = (len(df.index))
For:
RawData_ws['A1'].values = (len(df.index))

Tuple TypeError when assigning Value to Cell in openpyxl

I'm a first time user of openpyxl and am struggling with basic Cell editing.
In the following code I'm trying to change the Cell Value "B3" in my Excel File to a String Value (eg. "Germany").
What I don't seem to understand is why the openpyxl Worksheet & Worbook are an immutable tuple type and the Documentation is suggesting the simple Cell Assignment I'm using.
Here's my Code:
from openpyxl import Workbook
from openpyxl import load_workbook
# 1. Open Excel File
wb = Workbook()
wb = load_workbook(filename="myFile.xlsm", read_only=True, keep_vba=True, data_only=True)
ws = wb.active[1] # ws is the second Worksheet in the Workbook
# 2. Enter Input (Country)
ws["B3"] = "Germany"
wb.save("myFile.xlsm")
ws["B3"] = "Germany"
TypeError: 'tuple' object does not support item assignment
Expectation
I expected to find a Excel file that contains my assigned value in the given cell.
I appreciate every answer - thanks!
Line ws = wb.active[1] is probably wrong. Also you should use read_only=False (simply remove this param, the default is False) if you want to modify the file.
You can assign ws by name. If you don't know the names you can list them like this:
>>> wb.sheetnames
['Sheet1', 'Sheet2', 'Sheet3']
>>> ws = wb['Sheet2'] # or ws = wb.active - "Get the currently active sheet"
>>> ws["B3"] = "Germany"
Whole code:
from openpyxl import Workbook
from openpyxl import load_workbook
# 1. Open Excel File
wb = Workbook()
wb = load_workbook(filename="myFile.xlsm", keep_vba=True, data_only=True)
ws = wb.active # the currently active sheet
# 2. Enter Input (Country)
ws["B3"] = "Germany"
wb.save("myFile.xlsm")

Openpyxl: How to add filters to all columns

I can open a worksheet, how do I add the little filter menus to all columns without turning on any filters?
I can do it in xlsxwriter with
worksheet.autofilter(0, 0, 0, num_of_col)
How do I do it in openpyxl?
You can simply read ws.dimensions and it will return a string value with your range from "A1:XX". I used this to apply filters to my entire excel spreadsheet.
import openpyxl as px
wb= px.load_workbook('Data/Test01.xlsx')
ws = wb.active
ws.auto_filter.ref = ws.dimensions
wb.save('Data/Test03.xlsx')
All you need to do is to set worksheet.auto_filter.ref to the full range of worksheet cells.
import openpyxl
from openpyxl.utils import get_column_letter
workbook = openpyxl.load_workbook('Data/Test01.xlsx')
worksheet = workbook['Sheet1']
FullRange = "A1:" + get_column_letter(worksheet.max_column) \
+ str(worksheet.max_row)
worksheet.auto_filter.ref = FullRange
workbook.save('Data/Test03.xlsx')

Find range of filled contents in Excel worksheet

I have an Excel 2016 Book.xlsm. In the worksheet testsheet, the cells in the range A1:Y150 are filled with text or number contents. The upper-left cell is always A1.
I am using python v3 xlwings to open the Excel file.
import xlwings as xw
Book_name = 'C:/Users/name/Book.xlsm'
sheet_name = 'testsheet'
wb = xw.Book(Book_name)
sht = wb.sheets[sheet_name]
How do I find out the range of cells that are filled with contents using python, which in this case is A1:Y150?
You can get the range filled with contents with used_range:
import xlwings as xw
filename = "test.xlsx"
wb = xw.Book(filename)
ws = wb.sheets["SheetX"]
a_range = ws.used_range.address
print(a_range)
If wb is defined as Excel Workbook, then this is a good way:
print (wb.sheets[sheet_name].api.UsedRange.Address)

Formatting in OpenPyxl with use_iterators = True

This is similar to my earlier question getting formating data in openpyxl The only real difference is that now I really want to use the optimized workbook for the speed increase.
Basically I can't figure out how to retrieve formatting details when I use the optimized reader. Here's a toy sample, the comments explain what I'm seeing on the print statements. Am I doing something wrong? Is there a better way to retrieve formatting details?
Also, if anyone knows of a different excel reader for python that supports xlsx + retrieving formatting I'm open to changing! (I've already tried xlrd, and while that does support xlsx in the newer builds it doesn't yet support formatting)
from openpyxl import Workbook
from openpyxl.reader.excel import load_workbook
from openpyxl.style import Color, Fill
#this is all setup
wb = Workbook()
dest_filename = 'c:\\temp\\test.xlsx'
ws = wb.worksheets[0]
ws.title = 'test'
ws.cell('A1').value = 'foo'
ws.cell('A1').style.font.bold = True
ws.cell('B1').value = 'bar'
ws.cell('B1').style.fill.fill_type = Fill.FILL_SOLID
ws.cell('B1').style.fill.start_color.index = Color.YELLOW
wb.save(filename = dest_filename )
#setup complete
book = load_workbook( filename = dest_filename, use_iterators = True )
sheet = book.get_sheet_by_name('test')
for row in sheet.iter_rows():
for cell in row:
print cell.coordinate
print cell.internal_value
print cell.style_id #returns different numbers here (1, and 2 in case anyone is interested)
print sheet.get_style(cell.coordinate).font.bold #returns False for both
print sheet.get_style(cell.coordinate).fill.fill_type #returns none for bothe
print sheet.get_style(cell.coordinate).fill.start_color.index #returns FFFFFFFF (white I believe) for both
print
import openpyxl
print openpyxl.__version__ #returns 1.6.2
The style_ID appears to be the index for where you can find the style information in workbook -> shared_styles (book.shared_styles or sheet.parent.shared_styles).
In some workbooks this works flawlessly; but, I've also found in other workbooks the style_ID is greater than the length of shared_styles giving me "Out of range" Exceptions when I try to access said styles.

Categories

Resources