object of type 'NoneType' has no len() for setting column widths in openpyxl - openpyxl

In trying to get the widths of cells to autofit using openpyxl, I am running into the titular error with traceback to 'if len(cell.value) > column_widths[i]'.
def set_widths(ws):
from openpyxl.utils import get_column_letter
column_widths = []
for row in ws:
for i, cell in enumerate(row):
if len(column_widths) > i
if len(cell.value) > column_widths[i]:
column_widths[i] n= len(cell.value)
else:
column_widths += [len(cell.value)]
column_widths = np.array(column_widths)
column_widths = column_widths + 5
column_widths = list(column_widths)
for i, column width in enumerate(column_widths, 1):
ws.column_dimensions[get_column_letter(i)].width = column_width

Related

How can I modify the existing sheetobj.data_validations in openpyxl?

I am writing an application to create a new blank day's worth of cells in a financial transaction spreadsheet. The spreadsheet was generated by WPS.
Everything is working as I'd like, except that data validation for one column only does not copy successfully from the old cells to the new cells in the same column. When I examine the sheetobj.data_validations, I find that the working columns end like this:
M3217:M65536, E3217:E65536
The column that doesn't work correctly ends like this:
N3196:N3215
Here is the code that actually copies the cells:
for r in range(frod, eod):
for c in range(1, maxc + 1):
nrow = r + rinc
cell_tmp = sheet.cell(row = r, column = c)
val_tmp = cell_tmp.value
new_cell = sheet.cell(row = nrow, column = c)
new_cell.font = copy(cell_tmp.font)
new_cell.fill = copy(cell_tmp.fill)
new_cell.number_format = copy(cell_tmp.number_format)
new_cell.alignment = copy(cell_tmp.alignment)
new_cell.border = copy(cell_tmp.border)
headstr = col_string(sheet.title, c)
method = get_method(headstr)
#print('header string for col', c, 'is', headstr, 'form method is', method)
if cell_tmp.data_type is not 'f':
if method == 'cp_eod' and r == (eod - 2):
new_cell.value = val_tmp
else:
new_cell.value = None
new_cell.data_type = cell_tmp.data_type
elif method == 'tc_eod':
new_cell.value = form_self(val_tmp, r, nrow)
elif method == 'prev_inc':
if r == frod:
new_cell.value = form_inc(val_tmp, val_tmp[val_tmp.rindex('+')+1:])
else:
new_cell.value = date_prev(val_tmp, r, nrow)
elif method == 'self':
if r == eod:
#print('*** EOD ***')
new_cell.value = form_self_dec(val_tmp, r, nrow)
else:
new_cell.value = form_self(val_tmp, r, nrow)
elif method == 'self_fod':
if r == frod:
new_cell.value = form_self(val_tmp, r, nrow)
elif r == eod:
new_cell.value = form_self_dec(val_tmp, r, nrow)
else:
new_cell.value = form_frod(val_tmp, frod, frod + rinc, r, nrow)
elif method == 'self_eod':
new_cell.value = form_eod(val_tmp, r, nrow, eod, eod + rinc)
elif method == 'tcsbs':
new_cell.value = form_tcsbs(val_tmp, val_tmp[val_tmp.rindex('$')+1:])
elif method == 'self_prev':
if r == eod:
new_cell.value = form_prev(val_tmp, nrow)
else:
new_cell.value = form_self_dec(val_tmp, r, nrow)
The column in question falls into this block of code:
else:
new_cell.value = None
new_cell.data_type = cell_tmp.data_type
Is it possible to edit the sheetobj.data_validations for column N to end the same way the working columns do?
Other things I have tried:
Directly setting a new data validation for the cells in the column. Python showed the cells having data validation but when I saved the workbook and opened in google sheets, it was not there.
Copying a cell from a good column into the bad column on the original sheet.
This also did not solve my problem, when I copied a new block of cells, the data validation did not copy.
Copying a cell from a good column in another sheet into the bad column on the original sheet.
This resulted in losing all data validation when I copied a new block of cells.

xlrd copying cell style from xls to xlsx

Im trying to convert xls to xlsx files including cell style. At the moment, Im working with cell fonts.
Is there another way for xlrd to determine whether the cell font is bold or not other than font._font_flag == 1?
def xlstoxlsx():
input_file_loc = [x for x in os.listdir(path1) if x.endswith(".xls")]
count = 0
for file in input_file_loc:
xlsxwb = xlsxwriter.Workbook(f"{path1}/" + input_file_loc[count] + '_Coverted {:2d}.xlsx'.format(count))
xlswb = xlrd.open_workbook(path1 + "/" + file, formatting_info=True)
bold = xlsxwb.add_format({'bold': True})
italic = xlsxwb.add_format({'italic': True})
uline = xlsxwb.add_format({'underline': True})
for sht in xlswb.sheet_names():
xlsws = xlswb[sht]
rows, cols = xlsws.nrows, xlsws.ncols
all_rows = []
for row in range(rows):
curr_row = []
for col in range(cols):
curr_row.append(xlsws.cell_value(row, col))
all_rows.append(curr_row)
xlsxws = xlsxwb.add_worksheet()
for row in range(len(all_rows)):
for col in range(len(all_rows[0])):
cell = xlsws.cell(row, col)
font = xlswb.xf_list[cell.xf_index]
if font._font_flag == 1:
xlsxws.write(row, col, all_rows[row][col], bold)
elif font._font_flag == 0:
xlsxws.write(row, col, all_rows[row][col])
count += 1
xlsxwb.close()

How to multiply two Sparse matrices by Spars method with python?

I tried to multiply the two Sparse matrices, but I had trouble deleting extra rows that were all zeros, I usednumpy.delete(my_matrix, [n], axis=0)and got this error:
index 4 is out of bounds for axis 0 with size 3
def mult_mat(mat1, mat2):
col = mat1[0][1]
row = mat2[0][0]
row_mat1, row_mat2 = np.shape(mat1)[0], np.shape(mat2)[0]
if col != row:
return "Multiplication is not possible because the number" \
" of columns in the first matrix is opposite of the" \
" number of rows in the second matrix"
my_matrix = np.array([[0] * 3] * (mat1[0][2] * mat2[0][2]))
n = 0
for r in range(1, row_mat1):
for h in range(1, row_mat2):
if mat1[r][1] == mat2[h][0]:
my_matrix[n][0], my_matrix[n][1], my_matrix[n][2] = mat1[r][0], mat2[h][1], mat1[r][2] * mat2[h][2]
n += 1
row_my_matrix = np.shape(my_matrix)[0]
for n in range(row_my_matrix):
if my_matrix[n][0] == 0 & my_matrix[n][1] == 0 & my_matrix[n][2] == 0:
my_matrix = np.delete(my_matrix, [n], axis=0)
return my_matrix

Append array to itself by repeated function calls

im trying to append an array by repeatedly calling a function. When I put the append command in a loop this works fine, but not when the loop calls the function that's supposed to do the append.
import numpy as np
test_value = 555
i = 0
j = 0
test_array = np.empty([0, 3])
def test(test_value, i, j, test_array):
test_temp = []
test_temp.append(i)
test_temp.append(j)
test_temp.append(test_value)
test_temp_1 = test_temp
test_temp_2 = np.array(test_temp_1)
test_temp_2 = np.reshape(test_temp_2, (1,3))
test_array = np.append(test_array, test_temp_2, axis=0)
return test_array
for i in range(0,10):
i = i + 1
j = j + 2
test(test_value, i, j, test_array)
print ("test array", test_array)
Ideally what would happen is that test_array gets a new row added each time its looped, but so the final print of test_array stays empty.
Cheers

Dynamic labelling of shapes

I am creating shapes within an For-loop and I want each shape having a different name. Therefore, the Shape in Set Shape = ... in each iteration should have Shape replaced by a dynamic variable.
If I place shapes via Set Shape = w.Shapes.AddShape(msoShapeRectangle, 10,10,10,10) how can I have Shape (the name of the shape) be dynamic e.g. Set Cells(1 + i, 1) = w.Shapes.AddShape(msoShapeRectangle, 10,10,10,10) ... so that each shape has a different name. I also tried Shape.Name = which does not seem to have the same effect as setting the name while creating the shape.
I assign a name for each shape which I create within the loop:
Shape.Name = Cells(GanttStartRow + i, 1) & Cells(GanttStartRow + i, 2)
I set the connector via
Set conn = w.Shapes.AddConnector(msoConnectorElbow, 1, 1, 1, 1)
conn.ConnectorFormat.BeginConnect D, 1
conn.ConnectorFormat.EndConnect WP, 1 ... but receive a "type mismatch" error.
Assuming ws is the worksheet you are working with:
Dim s As Shape, i as integer
for i = 1 to 5
Set s = ws.Shapes.AddShape(msoShapeRectangle, 50 + i * 120, 200, 100, 100)
s.Name = "MyShapeName" & i
next i
You can later access the shapes by name:
For i = 1 To 5
Set s = ws.Shapes("MyShapeName" & i)
s.Fill.BackColor.RGB = RGB(0, 255 - i * 50, i * 50)
s.BackgroundStyle = i
Next i
However, an alternative is to loop over all shapes:
For Each s In ws.Shapes
Dim i As Integer
if left(s.Name, 1, 11) = "MyShapeName" then
i = Val(Mid(s.Name, 12))
s.Top = s.Top + i * 4
end if
Next s