How to use xlwings asynchronous mode with dynamic arrays? - xlwings

When using async_mode='threading' I noticed the following behaviour:
#xw.func(async_mode='threading')
#xw.ret(expand='table')
def test_fun():
time.sleep(2)
return [[0], [1], [2]]
The above code will output correctly 0, 1, 2 but this will output an array (ie the excel formula will have the {} brackets) and it will overwrite anything below it, ie won't use that spill warning and you can't edit it without editing the entire array.
#xw.func(async_mode='threading')
def test_fun():
time.sleep(2)
return [[0], [1], [2]]
This however which seems more desirable as it outputs a dynamic array (were I to remove the async_mode) only outputs 0 and the formula turns into #test_fun() and thus only returns the first value.
Experiencing this behaviour on v0.15.8

Your second example is the correct way of doing it and works for me. The first version is only if you specifically want to work with the legacy CSE arrays which is normally only the case when your version of Excel is not supporting dynamic arrays.
Just make sure to delete the CSE version of your formula completely, then re-import the function and simply call =test_fun() from a cell in Excel.
This should work from version v0.19.0 onwards - this was the issue that was being experienced. OP had v0.15.8.
https://github.com/xlwings/xlwings/issues/1277

Related

I have a google sheets cell with 5 different texts (from a dropdown) - how can I make another cell return a value based on the text

The 5 values in J4 are Studio, 1, 2, 3, 4.
Mortgage! is another sheet where I want to take B2*(52/12) if studio, B3*(52/12) if 1 and so on
Here is what I have been working with. I think I am close I just can't get it together to work
If
$J$4='Studio',(Mortgage!B2*(52/12)
$J$4='1',(Mortgage!B3*(52/12)
$J$4='2',(Mortgage!B3*(52/12)
$J$4='3',(Mortgage!B4*(52/12)
$J$4='4',(Mortgage!B5*(52/12)
Your logic is acceptable. You need to use the correct syntax.
=IF(
$J$4='Studio',Mortgage!B2*(52/12),
IF($J$4='1',Mortgage!B3*(52/12),
IF($J$4='2',Mortgage!B3*(52/12),
IF($J$4='3',Mortgage!B4*(52/12),
$J$4='4',Mortgage!B5*(52/12)
))))
By the way, it is customary to post a link to a public Google Sheet showing sample data when asking questions about Google Sheets.
Firstly, I think you have an errory in your sample code as you say I want to take B2*(52/12) if studio, B3*(52/12) if 1 and so on, but your sample is doing (Mortgage!B3*(52/12) for both $J$4='1' and $J$4='2'.
Therefor, I will assumne you are instead expecting...
if
$J$4='Studio',(Mortgage!B2*(52/12)
$J$4='1',(Mortgage!B3*(52/12)
$J$4='2',(Mortgage!B4*(52/12)
$J$4='3',(Mortgage!B5*(52/12)
$J$4='4',(Mortgage!B6*(52/12)
As others suggested, you can achive this by applying a nested IF() function with correct syntax,
but other than standard IF() funciont, you can use IFS() function for these kinds of cases:
=IFS(
$J$4='Studio',Mortgage!B2*(52/12),
$J$4='1',Mortgage!B3*(52/12),
$J$4='2',Mortgage!B4*(52/12),
$J$4='3',Mortgage!B5*(52/12),
$J$4='4',Mortgage!B6*(52/12)
)
There is also a SWITCH() function in google sheet that do similar things:
=SWITCH($J$4,
'Studio',Mortgage!B2*(52/12),
'1',Mortgage!B3*(52/12),
'2',Mortgage!B4*(52/12),
'3',Mortgage!B5*(52/12),
'4',Mortgage!B6*(52/12)
)
You may even create your own array to lookup for result:
=LAMBDA(DATA,
VLOOKUP($J$4,DATA,2,FALSE)
)({
'Studio',Mortgag!B2*(52/12);
'1',Mortgage!B3*(52/12);
'2',Mortgage!B4*(52/12);
'3',Mortgage!B5*(52/12);
'4',Mortgage!B6*(52/12)
})
where the array part:
{
'Studio',Mortgag!B2*(52/12);
'1',Mortgage!B3*(52/12);
'2',Mortgage!B4*(52/12);
'3',Mortgage!B5*(52/12);
'4',Mortgage!B6*(52/12)
}
can be shortened into something like this:
ArrayFormula({{'Studio';'1';'2';'3';'4'},Mortgage!B2:6*(52/12)})
or
ArrayFormula({{'Studio';TO_TEXT(SEQUENCE(4))},Mortgage!B2:6*(52/12)})
Combine this with the VLOOKUP(), you get this:
=ArrayFormula(VLOOKUP($J$4,{{'Studio';TO_TEXT(SEQUENCE(4))},Mortgage!B2:6*(52/12)},2,FALSE))
XLOOKUP() function also works in a similar way as VLOOKUP():
=ArrayFormula(XLOOKUP($J$4,{'Studio';TO_TEXT(SEQUENCE(4))},Mortgage!B2:6*(52/12)))

Is there a equivalent utassert.eqtable (Available in utplsql version 2.X) in utplsql version 3.3?

After going through the documentations of Utplsql 3.0.2 , I couldn't find any references the assertion api as available in the older versions. Please let me know whether is there a equivalent assertion like utassert.eqtable available in newer versions.
I have just recently gone through the same pain. Most utPLSQL examples out there are for utPLSQL v2. It transpires appears that the assertions have been deprecated, and have been replaced by "Expects". I found a great blog post by Jacek Gebal that describes this. I've tried to put this and other useful links a page about how unit testing fits into Redgate's Oracle DevOps pipeline (I work for Redgate and we often get asked how to best implement automated unit testing for Oracle).
I don't think you can compare tables straight away, but you can compare cursors, which is quite flexible, because you can, for instance, set-up a cursor with test data based on a dual query, and then check that against the actual data in the table, something like this:
procedure TestCursorExample is
v_Expected sys_refcursor;
v_Actual sys_refcursor;
begin
-- Arrange (Nothing really to arrange, except setting the expectation).
open v_Expected for
select 'me#example.com' as Email
from dual;
-- Act
SomeUpsertProc('me', 'me#example.com');
-- Assert
open v_Actual for
select Email
from Tbl_User
where UserName = 'me';
ut.expect(v_Actual).to_equal(v_Expected);
end;
Also, the example above works in Oracle 11, but if you're in 12c, apparently things got even easier, because you can use the table operator with locally defined types.
I've used a similar solution to verify that certain columns of a row were updated, while others were not. You can easily open a cursor for the original data, with some columns replaces by the new fixed values. Then do the update. Then open a cursor with the new actual data of all columns. You still have to write the queries, but it's way more compact than querying everything into variables and comparing those individually.
And, because you can open the 'expected' cursor before doing the actual 'act' step of the test, you can be sure that the query with 'expected' data is not affected by the test itself, and can even base that cursor on the data you are going to modify.
For comparing the data, the cursors are serialized to XML. This may have some side effects. In the test example above, my act step didn't actually do anything, so I got this difference, showing the count as well as showing the missing data.
If your cursors have more columns, and multiple difference, it can sometimes take a seconds to spot the differences between the XML tags. Also, there are currently some edge-case issues with this, I think because of how trimming works in XML.
1) testcursorexample
Actual: refcursor [ count = 0 ] was expected to equal: refcursor [ count = 1 ]
Diff:
Rows: [ 1 differences ]
Row No. 1 - Missing: <EMAIL>me#example.com</EMAIL>
at "MySchema.MyTestPackage", line 410 ut.expect(v_Actual).to_equal(v_Expected);
See also: 'comparing cursors' from utPLSQL 3 concepts

How to parse a matrix in Python?

I created a matrix of 0s using join(). Assignment works if I hotcode it. If I get as an input, it doesn't work.
theatre=[]
for i in range(5):
theatre.append(["0"]*5)
def print_screen(theatre):
for i in theatre:
print(" ".join(i))
print_screen(theatre)
theatre[int(raw_input("Enter row"))][int(raw_input("Enter col"))]=="x" ## this doesn't work
theatre[0][1]="x" ## This is working.
Oh Boy surely the problem you stated would exist in your code as it is NOT AT ALL A PROBLEM as far as python interpreter is considered.
See what you are doing
theatre[int(raw_input("Enter row"))][int(raw_input("Enter col"))]=="x" ## this doesn't work
is to compare if the value at a given point in the matrix is equal to x or not, so as far as your code goes python is comparing the given point and then just moving on to the next statement.
I would suggest that instead of asking here, it would be more helpful for you if you try to debug your code using print() statement or any debugger.

How to print content of a list of pointers in gdb?

I have the following list of pointers:
(here is a simple example, but in reality, my list could be componed by hundreds of entries)
{0xae5c4e8, 0xa09d4e8, 0xa753458, 0xae554e8}
I successfully print pointers content, one by one, by using :
p *(const Point *) 0xae5c4e8
How can I print contents of the preceding list in one command ?
There is no canned way to do this. It would be cool if you could type print *(*p # 23) -- using the # extension inside another expression, resulting in an implicit loop -- but you can't.
However, there are two decent ways to do this.
One way to do it is to use Python. Something like:
(gdb) python x = gdb.parse_and_eval('my_array')
(gdb) python
> for i in range(nnn):
> print x[i].dereference()
> end
You can wrap this in a new gdb command, written in Python, pretty easily.
Another way is to use define to make your own command using the gdb command language. This is a bit uglier, and has some (minor) limitations compared to the Python approach, but it is still doable.
Finally, once upon a time there was a gdb extension called "duel" that provided this feature. Unfortunately it was never merged in.
I don't think there is a simple way to show all the list elements at once. You could try to iterate through the items using:
set $it=mylist.begin()._M_node
print *(*(std::_List_node<const Point *>*)$it)._M_data
set $it=(*$it)._M_next
...
In the batch way. The problem is that the list items do not need to be located near to each other in the memory. To have better preview option in debug you could switch to the std::vector.
Hope this will help.
I have the following list of pointers:
You don't appear to have a list, you appear to have an array. Let's assume that it looks something like:
void *array[10] = {0xae5c4e8, 0xa09d4e8, 0xa753458, 0xae554e8};
You can print the first 4 dereferenced elements of that array like so:
(gdb) print ((Point**)array)[0]#4

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.