i am creating interactive excel, and i am using openpyxl library. For some reason excel cannot be loaded according to error with formula. There is how i put formula in cell:
ws = self.wb.create_sheet('help')
ws['C6'] = '=IFERROR(FILTER(other_sheet!B3:B12; other_sheet!D3:D12=main_sheet!C3; "No results"); "error")'
Formula work, when I directly pass them to excel, also the way i did is correct. Basic formulas instead of FILTER works (eg. sum). I assumed that this formula didnt work with openpyxl. And i should use built-in function in openpyxl but imo it won't work dynamically (eg. this statement: other_sheet!D3:D12=main_sheet!C3)
I saw that in manual is obligatory to use comas, so i applied it. But it still doesnt work
ws['C6'] = '=FILTER(other_sheet!B3:B12, other_sheet!D3:D12=main_sheet!C3, "No results")'
But it doesnt change anything, problem still appears. Any suggestions?
I also tried with ws['C6'].value
Related
I am trying to write a script using Xlwings and I have a formula that I need to insert into a column. I wrote a string that represents the formula and is correct because when I print the string and enter it into excel the formula works. However when I call it in xlwings using:
formulaColumnN = "= IF(INDEX('ZOR-ZCCK'!E:E,MATCH(E2&F2&H2&I2,'ZOR-ZCCK'!E:E&'ZOR-ZCCK'!F:F&'ZOR-ZCCK'!H:H&'ZOR-ZCCK'!I:I,0)-1)=\"TAPA\",INDEX('ZOR-ZCCK'!M:M,MATCH(E2&F2&H2&I2,'ZOR-ZCCK'!E:E&'ZOR-ZCCK'!F:F&'ZOR-ZCCK'!H:H&'ZOR-ZCCK'!I:I,0)-1),INDEX('ZOR-ZCCK'!M:M,MATCH(E2&F2&H2&I2,'ZOR-ZCCK'!E:E&'ZOR-ZCCK'!F:F&'ZOR-ZCCK'!H:H&'ZOR-ZCCK'!I:I,0)))"
sheet3.range("N2").formula = formulaColumnN
it does not work in fact when I look at what is in the cell I get this:
=# IF(#INDEX('ZOR-ZCCK'!E:E,MATCH(E2&F2&H2&I2,#'ZOR-ZCCK'!E:E&#'ZOR-ZCCK'!F:F&#'ZOR-ZCCK'!H:H&#'ZOR-ZCCK'!I:I,0)-1)="TAPA",INDEX('ZOR-ZCCK'!M:M,MATCH(E2&F2&H2&I2,#'ZOR-ZCCK'!E:E&#'ZOR-ZCCK'!F:F&#'ZOR-ZCCK'!H:H&#'ZOR-ZCCK'!I:I,0)-1),INDEX('ZOR-ZCCK'!M:M,MATCH(E2&F2&H2&I2,#'ZOR-ZCCK'!E:E&#'ZOR-ZCCK'!F:F&#'ZOR-ZCCK'!H:H&#'ZOR-ZCCK'!I:I,0)))
I have no clue why the # symbol is added and if I delete them the formula works. Please let me know if anyone knows why this is happening it has never done this on any other formula in xlwings.
Also conversely if someone knows how to convert this formula in Pandas because I tried but have been struggling to figure it out.
If you instead use sheet3.range("N3").formula2 = then you shouldn't have the problem (instead of just .formula.
I haven't looked into the differences extensively, I just know that this solves the problem, but the explanation can be found here if you want to read about it.
I'm using OpenPyxl to create and modify an Excel sheet.
I have the following formula in Excel:
=(SUM(IF(LEFT(Balances!$B$2:$B$100,LEN($B4))=$B4,Balances!$D$2:$D$100)))
This formula which is an "array formula" is working but in order to write it by hand, I have to finish with CTRL+SHIFT+ENTER (because it's an array formula).
This transform then the formula as follow:
{=(SUM(IF(LEFT(Balances!$B$2:$B$100,LEN($B4))=$B4,Balances!$D$2:$D$100)))}
I want to be able to write this formula via OpenPyxl with the following code:
sheet.cell(row=j, column=i).value = '{=(SUM(IF(LEFT(Balances!$B$2:$B$100,LEN($B4))=$B4,Balances!$D$2:$D$100)))}'
However, it doesn't work. OpenPyxl can't manage it. It give me the formula written but not working.
I could do it with XLSX Writer
https://xlsxwriter.readthedocs.io/example_array_formula.html
However XLSX writer doesn't work with already created files.
I don't see which path to follow.
Use the worksheet.formula_attributes to set the array formula. Place the formula in the desired cell, A1 for this example. Then set the formula_attributes to the cell range you want to apply the formula to.
ws["A1"] = "=B4:B8"
ws.formula_attributes['A1'] = {'t': 'array', 'ref': "A1:A5"}
In case solution provided above does not work, check whether you are using english name of functions in your formulae.
In my case I have been using czech function name and although formulae works if inserted manually, it did not work when inserted via openpyxl.
Switching to english name of the function solved the issue!
In my case the formula was using arrays for intermediate results before summarizing with a MAX. The formula worked OK when typed in but not when inserted via openpyxl. Office 365 version of Excel was inserting the new implicit intersection operator, #, incorrectly.
formula: ="Y" & MAX(tbl_mcare_opt[Year]*(tbl_mcare_opt[Who]=[#Who])*(tbl_mcare_opt[Year]<=intyear(this_col_name())))
It turns out that the properties needed to be set, as above. This allowed Excel to correctly interpret the formula. In my case the ref turned out to be just the single cell address.
I was able to determine that the formula was using dynamic arrays with a regex. If it was then I added the formula properties.
# provision for dynamic arrays to be included in formulas - notify excel
if is_formula(values[cn]):
regex_column=r'[A-Za-z_]+(\[\[?[ A-Za-z0-9]+\]?\])'
pattern=re.compile(regex_column)
matches=pattern.findall(values[cn])
if len(matches): # looks like a dynamic formula
address=get_column_letter(cix)+str(rix)
ws.formula_attributes[address]={'t':'array','ref': address}
I am trying to use xlwing's sheetname.range("Some object defined range").formula = "=Some excel formula" function, but I am not sure about how I can reference an object defined range as a string within the formula above.
I was able to define the object range as follows:
X = sht0.range('C10').expand('down').value
For all values within this range, I would like to perform a calcuation using an excel formula and I would like to use the following function.
sht0.range('F1').formula = "=SUM(X)"
It's a simple Sum function that could work if I just use the sum(X) function in python and use the result in the equation above without creating a string, but what if I would like to use any other built in excel functions instead?
One potential work around is using the xw.api syntax to create a "Named Range" in excel using the pywin32 syntax, but I can't seem to figure out what the syntax conversion would be.
As an example, in VBA it's:
Range("D7").Select
ActiveWorkbook.Names.Add Name:="SomeNameforaRange", RefersToR1C1:="=Sheet1!R7C4"
I tried the following in xlwings for python along with a few other attempts in the syntax:
sht0.range('C10').expand('down').api.Names = "SomeNameforaRange"
...but that doesn't work. It would just freeze my notebook or gives me an error.
Sorry if this question is very basic, I am a bit new to Python and xlwings, but I appreciate any help you may be to give.
I Want to access the cell which has formula from the excel workbook.Actually my python script is working fine only to read the data from excel, but i need that only the cell which has formula and to print that cells only
An example would be really appreciated..........
Two things that could help you solve the problem:
There's a typo: HasForumla instead of HasFormula
e is a string, not a cell object, so e.HasFormula won't work.
You probably want to use
e = sheet.cell(row,17)
to access the Cell object at that position. I'm not sure where you got your HasFormula attribute from, though - couldn't find it in the docs.
Edit:
I just looked at the README for the current distribution where it's stated that
xlrd will safely and reliably ignore any of these if present in the
file:
[...]
Formulas (results of formula calculations are extracted, of course).
[...]
I can set up an autofilter using pyWin32, but I wondered if it's possible to set a default filter and what the syntax would be.
For example, I'd like to set a filter on a year column and set the default for the current year.
xl = Dispatch("Excel.Application")
xl.Workbooks.Open(file_path)
xl.ActiveWorkbook.Worksheets(sheetname).Range("A2:A6").AutoFilter(1)
xl.ActiveWorkbook.Close(SaveChanges=1)
I've looked on the web for documentation on pywin32, and also Microsofts site, but can't work out how to translate the MS syntax to pywin32
Range("A2:A6").AutoFilter Field:=1, Criteria1:=rng.Value
I bumped into the same problem and after a bit of experimentation, I found that it was possible to set a range on the Columns attribute. Since I wanted to autofilter on columns A thru I, I set the criteria as follows:
xl.ActiveWorkbook.ActiveSheet.Columns("A:I").AutoFilter(1)
This worked for me. I'm assuming that you want to filter on Columns B thru F since AutoFilter is enabled only for columns. Perhaps the following criteria will work for you:
xl.ActiveWorkbook.ActiveSheet.Columns("B:F").AutoFilter(1)
Alok
The rather cryptic documentation is available at: http://msdn.microsoft.com/en-us/library/office/bb242013(v=office.12).aspx.
Each of the Excel VBA parameters translates to a function argument in pywin32. For example, if you want to filter all years that aren't equal to "2012" you would do this by specifying the Criteria1 parameter as follows:
MyYearRange.AutoFilter(Field=1, Criteria1="2012")
I'm just throwing an answer here for future people who want to use a different but similar solution. It is a lot more simple though. You will need to install xlwings and have pywin32. With xlwings, you can access the api functions of the pywin32 giving you a lot of flexibility on top of its own functions.
import xlwings
#puts the excel window into focus or opens it up. It evens work on csv files.
wb = xlwings.Book('C:\\Users\\yourusername\\Desktop\\Excel.xlsx')
#Choose the sheet you want to focus
datasht = wb.sheets['Sheet1']
#Pay attention to where you the .api. part. It matters if you are trying to achieve something specific. AND MAKE SURE to that you follow case-sensensitive typing for 'Range' and 'Autofilter'.
datasht.api.Range('A1:J10').AutoFilter(3,'SomeFilterValue')
Unfortunately, I'm not sure how to bring about the rest of the arguments. You pretty much just have to figure out how to translate the arguments into python. I did get it to work, but I'm unsure if you would run into any issues. here is one that would work
datasht.api.Range('A1:J10').AutoFilter(3,'filtervalue1',2,'filtervalue1',1)
Read the 2nd link specifically if you need to call on the Operator Parameter:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/range-autofilter-method-excel
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlautofilteroperator-enumeration-excel
If you need to select multiple filter values in the same column:
ws.Columns('ColumnLetter:ColumnLetter').AutoFilter(column_number, value_list, 7)
From https://learn.microsoft.com/en-us/office/vba/api/excel.xlautofilteroperator:
xlFilterValues | 7 | Filter values
This works:
Excel = win.Dispatch("Excel.Application")
Excel.visible = True
wb = Excel.Workbooks.open('path to xlsx')
ws = wb.Worksheets(1)
#use Range("A:A") for autofilter
ws.Columns("A:I").AutoFilter(1,"criteria string")
This will apply AutoFilter on Column A with Criteria1 is "criteria string"