I'm working on .odt report using py3o.template in Odoo. In the report, I need to add a number in a Group, so if I have 3 groups, It should print out : Group 1Group 2Group 3
I did it like in this image :
It doesn't work and I get these errors :
"Could not move siblings for '%s'" % py3o_base
py3o.template.main.TemplateException: Could not move siblings for
'with="i=1"'
Can you help me?
PS : I need to call "i" between Group and [date_start]
This error happens when you did not have close properly your tags.
I can see only one closing with, try to close the two others.
Check the following example:
with="index=1"
with="index=index+1"
with="index=index+1"
function="index" index=3
/with
function="index" index=2
/with
function="index" index=1
/with
function="index" index undefined
Note that if a variable of the same name already existed outside of the scope of the with directive, it will not be overwritten. Instead, it will have the same value it had prior to the with assignment. Effectively, this means that variables are immutable.
To avoid that we can use a list to hold indexes and in each iteration we will create a new variable to hold the new index (we can use list.pop(0) to remove the previous index).
with="index=[1]"
for="item in range(4)"
function="index[-1]"
with="_=index.append(index[-1]+1)"
/with
with="_=index.pop(0)"
/with
/for
At the end index = function="str(index)"
/with
The output should be:
1
2
3
4
At the end index == [5]
To enumerate the loop items I highly recommend using enumerate function.
for="index,d in enumerate(o.get_session_date_ids(), 1)"
function="index"
Related
Hello I have a list with temperature values:
temperatures=[-2,1,10.2,6,15,-6,20,13.5,0.9,-8.3]
and I want to create 2 list containing 1 the values above zero and the other the values below. It is an exercise and I have to use for loop and conditional statment.
I created two additional empty values and I try to use the conditional statment to select the two ranges of values to complete the task, but Iàm not reaching the objective. Could you help?
this is the code I tried:
```
temperatures=[-2,1,10.2,6,15,-6,20,13.5,0.9,-8.3]
temp_below_zero=[]
temp_above_zero=[]
for i in range(len(temperatures):
if i < 0 :
temp_below_zero.append(i)
elif i > 0 :
temp_above_zero.append(i)
print(temp_below_zero,temp_above_zero)
```
`
```
You enumerated the value 'i', but didn't use it as an indexer for the list. You could either do this, or just iterate over each element in the list by itself:
temperatures=[-2,1,10.2,6,15,-6,20,13.5,0.9,-8.3]
temp_below_zero=[]
temp_above_zero=[]
for i in temperatures:
if i < 0 :
temp_below_zero.append(i)
elif i > 0 :
temp_above_zero.append(i)
print(temp_below_zero,temp_above_zero)
or using indexing (which I think you initially wanted to do):
temperatures=[-2,1,10.2,6,15,-6,20,13.5,0.9,-8.3]
temp_below_zero=[]
temp_above_zero=[]
for i in range(len(temperatures)):
if temperatures[i] < 0 :
temp_below_zero.append(temperatures[i])
elif temperatures[i] > 0 :
temp_above_zero.append(temperatures[i])
print(temp_below_zero,temp_above_zero)
This approach is very close and you are definitely on the right track. Take a look at your for loop.
for i in range(len(temperatures):
The loop, in this case, will run from values 0 to 10 (not including 10) stored as i. If instead, you want i to store each of the values in the list, rewrite your loop like this:
for i in temperatures:
This modification makes it so that i contains a value in the list through each iteration, instead of the indices of the list. I hope this is helpful!
I'm trying to create individual dictionary entries while looping through some input data. Part of the data is used for the key, while a different part is used as the value associated with that key. I'm running into a problem (due to Python's "everything is an object, and you reference that object" operations method) with this as ever iteration through my loop alters the key set in previous iterations, thus overwriting the previously set value, instead of creating a new dict key and setting it with its own value.
popcount = {}
for oneline of datafile:
if oneline[:3] == "POP":
dat1, dat2, dat3, dat4, dat5, dat6 = online.split(":")
datid = str.join(":", [dat2, dat3])
if datid in popcount:
popcount[datid] += int(dat4)
else:
popcount = { datid : int(dat4) }
This iterates over seven lines of data (datafile is a list containing that information) and should create four separate keys for datid, each with their own value. However, what ends up happening is that only the last value for datid exist in the dictionary when the code is run. That happens to be the one that has duplicates, and they get summed properly (so, at least i know that part of the code works, but the other key entries just are ... gone.
The data is read from a file, is colon (:) separated, and treated like a string even when its numeric (thus the int() call in the if datid in popcount).
What am I missing/doing wrong here? So far I haven't been able to find anything that helps me out on this one (though you folks have answered a lot of other Python questions i've run into, even if you didn't know it). I know why its failing; or, i think i do -- it is because when I update the value of datid the key gets pointed to the new datid value object even though I don't want it to, correct? I just don't know how to fix or work around this behavior. To be honest, its the one thing I dislike about working in Python (hopefully once I grok it, I'll like it better; until then...).
Simply change your last line
popcount = { datid : int(dat4) } # This does not do what you want
This creates a new dict and assignes it to popcount, throwing away your previous data.
What you want to do is add an entry to your dict instead:
popcount[datid] = int(dat4)
There is a simple cursor, which has 260 records. Inside the loop not only print but update some tables. There is not only code, but explanation
/*Declare cursor for read only*/
DECLARE crsr_one CURSOR FOR
SELECT a,b,c,d
FROM table_name
WHERE a>=100
for read only
OPEN crsr_one /*open cursor*/
DECLARE #a,#b,#c,#d /*declare loop variables*/
while (1=1) /*start while loop*/
BEGIN
FETCH crsr_one into #a,#b,#c,#d /*fetch into variable */
IF (##sqlstatus = 2) /*Break if no more records*/
break
/*some other code with select and update table*/
print "%1! %2! %3! %4!", #a,#b,#c,#d /*Print variables*/
END
The problem is:
In the while loop it became infinitive and brings the same data.
Any idea why and how to correct it?
Your code looks good (except that the syntax for the DECLARE is invalid).
If the loop doesn't break on ##sqlstatus = 2, then the obvious question is: what value does it have? It can also be '1', indicating an error. To find out, print the value.
To be fully correct you should therefor also test for ##sqlstatus = 1. The easiest way to do this is to test for ##sqlstatus != 0 which covers both values 1 and 2.
I am trying to pass a variable from the first loop into the next. Why am I doing this? Well they both have the same key. Here is an example of trying to pass the index from the first loop into the second. Both values end up being the $idx of the second loop. How can this be done?
{#first}
{#second firstIDX="{$idx}"}
{firstIDX} : {$idx}<br>
{/second}
{/first}
I managed to get this working using the following (dot notation and no quotes):
{#first}
{#second firstIDX=$idx firstID=._id}
{firstIDX} : {$idx}<br>
{firstID} : {_id}<br>
{/second}
{/first}
I have a manual list I created in a macro in stata, something like
global list1 "a b c d"
which I later iterate through with something like
foreach name in $list1 {
action
}
I am trying to change this to a DB driven list because the list is getting big and changing quickly, I create a new $list1 with the following commands
odbc load listitems=items, exec("SELECT items from my_table")
levelsof listitems
global list1=r(levels)
The items on each are the same, but this list seems to be different and when I have too many items it break on the for loop with the error
{ required
r(100);
Also, when I run only levelsof listitems I get the output
`"a"' `"b"' `"c"' `"d"'
Which looks a little bit different than the other macros.
I've been stuck in this for a while. Again, it only fails when the number of items becomes large (over 15), any help would be very appreciated.
Solution 1:
levelsof listitems, clean local(list1)
foreach name of local list1 {
...action with `name'...
}
Solution 2:
levelsof listitems, clean
global list1 `r(levels)'
foreach name of global list1 {
...action with `name'...
}
Explanation:
When you type
foreach name in $list1 {
then whatever is in $list1 gets substituted inline before Stata ever sees it. If global macro list1 contains a very long list of things, then Stata will see
foreach name in a b c d e .... very long list of things here ... {
It is more efficient to tell Stata that you have a list of things in a global or local macro, and that you want to loop over those things. You don't have to expand them out on the command line. That is what
foreach name of local list1 {
and
foreach name of global list1 {
are for. You can read about other capabilities of foreach in -help foreach-.
Also, you originally coded
levelsof listitems
global list1=r(levels)
and you noted that you saw
`"a"' `"b"' `"c"' ...
as a result. Those are what Stata calls "compound quoted" strings. A compound quoted string lets you effectively nest quoted things. So, you can have something like
`"This is a string with `"another quoted string"' inside it"'
You said you don't need that, so you can use the "clean" option of levelsof to not quote up the results. (See -help levelsof- for more info on this option.) Also, you were assigning the returned result of levelsof (which is in r(levels)) to a global macro afterward. It turns out -levelsof- actually has an option named -local()- where you can specify the name of a local (not global) macro to directly put the results in. Thus, you can just type
levelsof listitems, clean local(list1)
to both omit the compound quotes and to directly put the results in a local macro named list1.
Finally, if you for some reason don't want to use that local() option and want to stick with putting your list in a global macro, you should code
global list1 `r(levels)'
rather than
global list1=r(levels)
The distinction is that the latter treats r(levels) as a function and runs it through Stata's string expression parser. In Stata, strings (strings, not macros containing strings) have a limit of 244 characters. Macros containing strings on the other hand can have thousands of characters in them. So, if r(levels) had more than 244 characters in it, then
global list1=r(levels)
would end up truncating the result stored in list1 at 244 characters.
When you instead code
global list1 `r(levels)'
then the contents of r(levels) are expanded in-line before the command is executed. So, Stata sees
global list1 a b c d e ... very long list ... x y z
and everything after the macro name (list1) is copied into that macro name, no matter how long it is.