xlwings - Automation error for simple UDF function setting cell value - xlwings

I have a fairly basic function that is supposed to set a cell value (in theory a DataFrame, but I've replaced that with 1 as part of my debugging).
#xl.func
def RT_GetChartData():
excel = xl.Book.caller()
excel.app.display_alerts = False #I do this because I keep getting OLE errors
excel.sheets("EventDates").range("TempEventOutput").value = 1
return "done"
When I call this function from Excel, it sometimes sets the cell to 1 (but not every time, as I've replaced that with 2, 3, etc and doesn't update), and the cell returns simply
"Automation error"
Any ideas on whats going on... ? I've confirmed that the object types are correct, ie Book, Sheet, Range, so I dont think it's that...

Related

Google sheets - How to compare a formula within a cell with a string to spot changes in the formula?

I help a small business with an application which is entirely run from google sheets and google forms. The issue is that from time to time the business owner will go into the sheet and delete rows of old data. I've noticed that as a result, some of the formulas will change the row which they are looking at. This is despite me using explicit cell references such as $A$1 for example.
So what I would like to do, is use somehow compare the cell which contains the formula, with a string of what the formula should be, then return a value if the formula matches. I had thought an =If function would solve this but so far I am not having any luck.
This is what I have used so far:
Lets say cell A1 contains the formula I want to check and the formula is (this works fine): =FILTER(Dashboard!A2:A, Dashboard!C2:C1 = TODAY())*
I am using =IF(A1="=FILTER(Dashboard!A2:A, Dashboard!C2:C*1 = TODAY())",True,False)
I am expecting the function to compare the value of A1 with my string and return the value True. If the formula does not match the string it should return the value False.
I currently am returning the value of False despite the formula and string being an exact match. I assume this is because my =If statement is looking at the value returned by the =Filter function rather than the formula itself.
Any help would be appreciated.
thanks
You could just use INDIRECT() in the place of explicit cell ($A$1) reference you mentioned and that should solve the problem of formulas going haywire due to rows deletion in Form Responses tab. Please do test it out.
INDIRECT("Sheet!"&A1)
INDIRECT("A1")

Is there a way to check the value of the cell to the left and add two to the count, unless there is a value entered in another cell in the same row?

I am trying to write a piece of code in Google Sheets that automatically creates a follow-up date based on the date in the immediate left cell. It gets that date, and adds two (days) to it. Then that date gets pushed into Appsheet, where it is marked on a virtual calendar.
I also want the code to recognize when something is filled into the "Status" section (which is located in the 4th cell to the right) and fill in the current cell with something like "Done".
Currently, everything I have works except for that last part, when something is entered into the Status column I get an error that reads;
Function IF parameter 1 expects boolean values. But 'Declined' is a
text and cannot be coerced to a boolean.
I believe that means I need to convert the data in the status column into a boolean value, but I have no idea how to proceed in doing that. See below code;
=IF(INDIRECT("RC[4]",0), "Done", INDIRECT("RC[-1]",0) +2)
Let me know what you guys think, and thank you in advance for your help 👍
try:
=IF(INDIRECT("RC[4]",0)="Declined", "Done", INDIRECT("RC[-1]",0) +2)
or:
=IF(INDIRECT("RC[4]",0)<>"Declined", "Done", INDIRECT("RC[-1]",0) +2)

Is there a way to have an IF statement look for even or odd numbers?

I am very new to coding and am trying to make a camera check out/check-in system using a google form and google sheet. I am using a bar code scanner to scan in the camera on the google form which is linked then to the google sheet. Right now I am trying to get the sheet to count how many times the bar code was scanned in and then based on that tell me if the camera is checked in or out. So if the bar code is scanned in only once I now someone checked it out but if it is scanned twice I know it has been returned and then when it appears a third time it is checked out again and so on and so forth.
I have already tried using LOOKUP but it only searches one row and I want to be able to check in several items at once. I also tried using VLOOKUP but it doesn't work either.
This is the code that I have so far but it only works once since it only looks if a code has been scanned in once or several times
=If(COUNTIF(Data_Entered!$E$2:$I$6,A2) = 0, "Check In", "Check Out")
I want it that instead of only saying = 0 that I can say = even numbers.
You can use MOD. Ex.) =MOD(A1,2)
It will return a 1 if odd, 0 if even.
=IF(ISODD(COUNTIF(A2:A, "<>")), "online", "ofline")
=ARRAYFORMULA(IF(LEN(A2:A), IF(ISODD(IF(A2:A<>"", ROW(A1:A), )), "on", "off"), ))

Xlrd list index out of range

I'm just starting to explore Xlrd, and to be honest am pretty new to programming altogether, and have been working through some of their simple examples, and can't get this simple code to work:
import xlrd
book=open_workbook('C:\\Users\\M\\Documents\\trial.xlsx')
sheet=book.sheet_by_index(1)
cell=sheet.cell(0,0)
print cell
I get an error: list index out of range (referring to the 2nd to last bit of code)
I cut and pasted most of the code from the pdf...any help?
You say:
I get an error: list index out of range (referring to the 2nd to last
bit of code)
I doubt it. How many sheets are there in the file? I suspect that there is only one sheet. Indexing in Python starts from 0, not 1. Please edit your question to show the full traceback and the full error message. I suspect that it will show that the IndexError occurs in the 3rd-last line:
sheet=book.sheet_by_index(1)
I would play around with it in the console.
Execute each statement one at a time and then view the result of each. The sheet indexes count from 0, so if you only have one worksheet then you're asking for the second one, and that will give you a list index out of range error.
Another thing that you might be missing is that not all cells exist if they don't have data in them. Some do, but some don't. Basically, the cells that exist from xlrd's standpoint are the ones in the matrix nrows x ncols.
Another thing is that if you actually want the values out of the cells, use the cell_value method. That will return you either a string or a float.
Side note, you could write your path like so: 'C:/Users/M/Documents/trial.xlsx'. Python will handle the / vs \ on the backend perfectly and you won't have to screw around with escape characters.

How to iterate over all the page breaks in an Excel 2003 worksheet via COM

I've been trying to retrieve the locations of all the page breaks on a given Excel 2003 worksheet over COM. Here's an example of the kind of thing I'm trying to do:
Excel::HPageBreaksPtr pHPageBreaks = pSheet->GetHPageBreaks();
long count = pHPageBreaks->Count;
for (long i=0; i < count; ++i)
{
Excel::HPageBreakPtr pHPageBreak = pHPageBreaks->GetItem(i+1);
Excel::RangePtr pLocation = pHPageBreak->GetLocation();
printf("Page break at row %d\n", pLocation->Row);
pLocation.Release();
pHPageBreak.Release();
}
pHPageBreaks.Release();
I expect this to print out the row numbers of each of the horizontal page breaks in pSheet. The problem I'm having is that although count correctly indicates the number of page breaks in the worksheet, I can only ever seem to retrieve the first one. On the second run through the loop, calling pHPageBreaks->GetItem(i) throws an exception, with error number 0x8002000b, "invalid index".
Attempting to use pHPageBreaks->Get_NewEnum() to get an enumerator to iterate over the collection also fails with the same error, immediately on the call to Get_NewEnum().
I've looked around for a solution, and the closest thing I've found so far is http://support.microsoft.com/kb/210663/en-us. I have tried activating various cells beyond the page breaks, including the cells just beyond the range to be printed, as well as the lower-right cell (IV65536), but it didn't help.
If somebody can tell me how to get Excel to return the locations of all of the page breaks in a sheet, that would be awesome!
Thank you.
#Joel: Yes, I have tried displaying the user interface, and then setting ScreenUpdating to true - it produced the same results. Also, I have since tried combinations of setting pSheet->PrintArea to the entire worksheet and/or calling pSheet->ResetAllPageBreaks() before my call to get the HPageBreaks collection, which didn't help either.
#Joel: I've used pSheet->UsedRange to determine the row to scroll past, and Excel does scroll past all the horizontal breaks, but I'm still having the same issue when I try to access the second one. Unfortunately, switching to Excel 2007 did not help either.
Experimenting with Excel 2007 from Visual Basic, I discovered that the page break isn't known unless it has been displayed on the screen at least once.
The best workaround I could find was to page down, from the top of the sheet to the last row containing data. Then you can enumerate all the page breaks.
Here's the VBA code... let me know if you have any problem converting this to COM:
Range("A1").Select
numRows = Range("A1").End(xlDown).Row
While ActiveWindow.ScrollRow < numRows
ActiveWindow.LargeScroll Down:=1
Wend
For Each x In ActiveSheet.HPageBreaks
Debug.Print x.Location.Row
Next
This code made one simplifying assumption:
I used the .End(xlDown) method to figure out how far the data goes... this assumes that you have continuous data from A1 down to the bottom of the sheet. If you don't, you need to use some other method to figure out how far to keep scrolling.
Did you set ScreenUpdating to True, as mentioned in the KB article?
You may want to actually toggle it to True to force a screen repaint. It sounds like the calculation of page breaks is a side-effect of actually rendering the page, rather than something Excel does on demand, so you have to trigger a page rendering on the screen.