Python Forum
Updating formulas in Excel - best solution
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Updating formulas in Excel - best solution
#1
Hello,

I'm working on automatizing one report using Python.
In general I have around 20 excel files (.xlsx and .xlms) that I filter base on some criteria and then copy&paste to final report. At the end I dropdown/autofill formulas in the final report (from first row till end) - I assume it will save some time in preparing report.

Is below code best way of dropdown/autofill formula)? I need of course keep reference updates (meaning AO11, AO12, AO13 ect).


# Loop over each row in the range
for row in range(start_row, end_row + 1):
    # Adjust the formula for each row
    adjusted_formula = formula_AP10.replace("10", str(row))  # Update the row reference
    adjusted_formula = adjusted_formula.replace("AO10", f"AO{row}")  # Update the AO10 reference   
    adjusted_formula = adjusted_formula.replace("AN10", f"AN{row}")  # Update the AN10 reference
                   
    # Set the adjusted formula to the current cell in column AP
    MPV1[f"AP{row}"].value = adjusted_formula         
Reply
#2
Did you solve the problem?
Reply
#3
(Mar-04-2024, 10:23 AM)Aften1961 Wrote: Did you solve the problem?

Partially. I might use translate as below. But to be honest I more willing of creating VBA and launch it using Python.
Translate solution seems be sensitive for what kind of data are copied/included in Excel. Using "translate" solution not always cooperate with my files as for my report I use data from different sources. With VBA I don't have such issue.


#Version 3
from openpyxl import load_workbook
from openpyxl.formula.translate import Translator

# Load the workbook
wb = load_workbook('_MAT_TEMPLATE_Python.xlsx')
ws = wb["Material prices"]

# Get the total number of rows based on column A
total_rows = sum(1 for row in ws.iter_rows(max_col=1, max_row=ws.max_row, values_only=True) if row[0])

# Generate the formula for column B
orig_formula = "=VLOOKUP($A7,'Master data'!$A:$H,2,0)"
orig_cell = 'B7'
ws[orig_cell] = orig_formula

# Apply formulas in column B
for row in range(8, total_rows+1):

    dst_cell = f"B{row}"
    # Apply the formula to the cell translating from cell B7
    ws[dst_cell] = Translator(orig_formula, origin=orig_cell).translate_formula(dst_cell)

# Save the workbook
wb.save("_MAT_TEMPLATE_Python.xlsx")
Reply
#4
Seems like a recipe for disaster, shifting formula references around!

This should move all formulas by a fixed amount (addrows) to cells further down and change the formulas to cells addrows further down.

Is that what you want to do?

What about the data? Do you need to move it?

What about the old formulas? Do you need to delete them?

You can easily make a function to move formulas to the right by a fixed amount too.

import openpyxl
import re

path2XL = '/home/pedro/myPython/openpyxl/xlsx_files/'
XLfile = 'XL_with_formulas.xlsx'
savename = 'changedXL.xlsx'

sF = openpyxl.load_workbook(path2XL + XLfile)
sheets = sF.sheetnames # only 1 sheet here: ['formulas']

def findFormula_coords(ws, startrow, startcol, maxrow, maxcol):    
    for row in ws.iter_rows(min_row=startrow, min_col=startcol, max_row=maxrow, max_col=maxcol):
        yield [cell.coordinate for cell in row if cell.data_type == 'f']

# find all cells in a range which contain formulas
# returns a list of lists
oldcells = [i for i in findFormula_coords(sF['formulas'], 2, 1, 11, 6)]

# don't really need this
##def findFormula(ws, startrow, startcol, maxrow, maxcol):    
##    for row in ws.iter_rows(min_row=startrow, min_col=startcol, max_row=maxrow, max_col=maxcol):
##        yield [cell.value for cell in row if cell.data_type == 'f']
##oldformulas = [i for i in findFormula(sF['formulas'], 2, 1, 11, 6)]

def copyFormula_down(oldcells, addrows):
    # oldcells is a list with the coordinates of each cell in a row which contains a formula like ['C2', 'D2', 'E2', 'F2']
    for j in range(len(oldcells)):
        oldFormula = sF['formulas'][oldcells[j]].value # like: '=A2*B2'
        rownum = re.search(r"\d+", oldcells[j]) # if oldcells[j] like 'C2' will find '2'
        # increment the row number
        newrownum = int(rownum[0]) + addrows
        newCell = re.sub('\d+', str(newrownum), oldcells[j])
        # find all cells named in the formula, I hope!
        cells = re.findall(r"[A-Z]+\d+", oldFormula) # returns a list like ['A2', 'B2']
        newcells = []
        for c in range(len(cells)):
            oldnum = re.search(r"\d+", cells[c]) # find the number in a string like 'A2'     
            newnum = int(oldnum[0]) + addrows # add the required number of rows
            newcell = re.sub('\d+', str(newnum), cells[c]) # change 'A2' to 'A17' or similar 
            newcells.append(newcell) # make a list of the new cells for formulas
        for c in range(len(cells)):
            print(f"Old cell coordinates {cells[c]}, new cell coordinates {newcells[c]}") # old cell, new cell coordinates
            newFormula = re.sub(cells[c], newcells[c], oldFormula)
            # overwrite oldformula or only 1 part will be changed
            # the list of cell coordinates in the formula could be long!
            oldFormula = newFormula
        sF['formulas'][newCell].value=newFormula
        # overwrite the old file, or save as a new file
        # sF.save(path2XL + savename)
        sF.save(path2XL + XLfile)

addrows = 20
for i in range(len(oldcells)):
    # oldcells[i] is a list
    copyFormula_down(oldcells[i], addrows)

print('Moved all formulas down {addrows} rows. Maybe we need to move the data too? And delete the old formulas?')
This copied all formulas to 20 rows further down and changed the formula cell references accordingly.

Sadly, the new references contain no data, so all formulas show zero!
Reply
#5
Quote:This should move all formulas by a fixed amount (addrows) to cells further down and change the formulas to cells addrows further down.

Is that what you want to do?

I don't want use " fixed amount (addrows)" as range/base for the formulas will be different each month.


Quote:What about the data? Do you need to move it?

Not sure which "data" do you mean.

Quote:What about the old formulas? Do you need to delete them?

There are no old formulas. Only formula can be in the first row. Next the formulas needs to be filled down


Thanks for the code. Will try to adjust it (remove fixed amount) and test it.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python openyxl not updating Excel file MrBean12 1 345 Mar-03-2024, 12:16 AM
Last Post: MrBean12
  plotting based on the results of mathematical formulas Timur 1 353 Feb-08-2024, 07:22 PM
Last Post: Gribouillis
  Updating sharepoint excel file odd results cubangt 1 856 Nov-03-2023, 05:13 PM
Last Post: noisefloor
  openpyxl insert list with formulas Irv1n 1 1,566 Sep-16-2021, 08:10 AM
Last Post: Irv1n
  Help with a query - to show possible formulas Yanos 1 1,778 Nov-02-2020, 12:18 AM
Last Post: jefsummers
  How to ignore formulas when reading excel file SriMekala 3 6,537 Aug-16-2019, 04:04 PM
Last Post: buran
  python 3 math formulas where to use () Python101 1 2,313 Jun-09-2019, 09:54 PM
Last Post: micseydel
  Business formulas more help needed!! jy0013 4 3,441 Aug-29-2017, 12:21 AM
Last Post: jy0013

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020