openpyxl - col_idx, column, column_letter in versions gt 2.5.8 - openpyxl

With thousands of lines of code that uses openpyxl, we updated openpyxl (to version 2.6.2) and it appears that a change that affects backwards-compatibility has missed documentation.
Can someone (Charlie?) please confirm that .column - which formerly returned a letter - now returns a number, and a new method .column_letter must be used to return the letter? (Did I understand that correctly from the docs?)
In the new version, is there now any difference between what is returned from .column and .col_idx? (Do these basically return the same thing, or is one zero-based and the other one-based? Or...?)
To update our code, if we just search/replace the .column (expecting the column's letter) with .column_letter - is there anything else to be aware of? (For E.G. Will the col ltr being returned by .column_letter be offset at all, or exactly the same as the old .column ?)

Yes, there were some significant changes in OpenPyXL 2.6+ that somehow missed adequate documentation.
An even larger change to be aware of -- because it also affects the .column/.column_letter methods -- is the functionality of .merge_cells.
It is no longer possible to use either .column_letter or .col_idx on a cell in a merged range - you must either use .column (for a number), or the get_column_letter(cell) method for a letter. (Note that you must import method get_column_letter from utils:
from openpyxl.utils import get_column_letter
Now, to answer your specific questions:
1) Yes, you must now use .column_letter (no longer .column) to get the column letter - but as mentioned above, it is safer to use get_column_letter(cell). And yes, .column will now return a number, not a letter.
2) Yes, .column now returns a number, exactly like .col_idx. In fact, I recommend against using .col_idx any longer since it no longer works on cells within a merged cell range.
3) Replace .column with get_column_letter(cell) instead of .column_letter due to changes with handling of merged cell ranges. So a simple search/replace would not be adviseable. Outside of merged cells, however, .column_letter now returns what .column used to do.

Related

Bug in Google Sheets Formatting

I believe I may have found a bug in Google Sheets formatting or else my preferred option is I'm doing something wrong! * Brief rant - I find GridRange a PITBS!! Rant over.
I'm simply trying to format a cell and make the text bold. I send the following JSON request:
{"requests":[{"repeatCell":{"range":{"startRowIndex":1,"endRowIndex":"2","startColumnIndex":1,"endColumnIndex"
:2,"sheetId":0},"cell":{"effectiveFormat":{"textFormat":{"bold":"true"}}},"fields":"*"}},{"repeatCell"
:{"range":{"startRowIndex":7,"endRowIndex":"8","startColumnIndex":1,"endColumnIndex":7,"sheetId":0},"cell"
:{"effectiveFormat":{"textFormat":{"bold":"true"}}},"fields":"*"}}]}
And the values in the cells disappear?? I know the values are there because if I omit this styling code then nothing is altered and the values remain. What am I doing wrong? (For ref the fields here are B2:B2 and B8:G8). Any help gratefully appreciated.
I am sending this through the JS API but believe I have seen the same through the PHP too.
You are setting the fields parameter to *, which means, "I want to set every field.". Since you don't supply a value but said you want to set each field, the values are being reset to their defaults (which is empty).
If you only want to apply formatting, you need to set the fields parameter to just the format fields, e.g userEnteredFormat. See the documentation on field masks for more info.
Note also that you're attempting to set effectiveFormat, but per the reference docs that field is read-only.

MS Access: eval() returns NULL when accessing .Column(x, y) property

I have a form and to validate it, I am using eval(). Background is, that I have defined rules in an table. These rules contain placeholders. The rule is compiled and then eval() should check wether its true or false.
Part of one rule contains a check on a listbox value. I identified this to be the problem. I could reduce it to the following:
Application.Forms("frmDMAE").lstHistory.Column(6, Application.Forms("frmDMAE").lstHistory.ListCount - 1)
returns ie 2,
eval("Application.Forms(""frmDMAE"").lstHistory.Column(6, Application.Forms(""frmDMAE"").lstHistory.ListCount - 1)")
returns NULL - but I can not figure out why!?
eval("Application.Forms(""frmDMAE"").lstHistory.Column(6, 5)")
returns NULL as well!? Column 6, row 5 definately contains a numeric value.
Also pasting the following into the debug window shows "2" as return value in both cases:
Application.Forms("frmDMAE").lstHistory(6, Application.Forms("frmDMAE").lstHistory.ListCount - 1)
Application.Forms("frmDMAE").lstHistory.Column(6, 5)
Any idea anyone??? I don't have a dime anymore.
[EDIT]
Solution of Andre works. Just change the indexes of the .Column property within Eval(). Use .Column(rowindex, colindex) instead of .Column(colindex, rowindex)!
[/EDIT]
Thank You very much,
Thomas
Wow. What a strange thing.
Apparently you have to switch the parameters (or array indexes) of the .Column property around when using it with Eval().
My listbox has 2 rows and 7 columns, with a number in the 6th column (= column 5).
? Forms!myForm!myList.Column(5,1)
3600
? Eval("Forms!myForm!myList.Column(5,1)")
Null
? Eval("Forms!myForm!myList.Column(1,5)")
3600
I don't really know what to make of this.
Note: I'm using Access 2010.

Is binary identical output possible with XlsxWriter?

With the same input is it possible to make the output binary identical using XlsxWriter?
I tried changing the created property to the same date and that helped a little. Still get a lot of differences in sharedStrings.xml.
Thanks
Yes for identical input, if you set the created date in the worksheet properties:
import xlsxwriter
import datetime
for filename in ('hello1.xlsx', 'hello2.xlsx'):
workbook = xlsxwriter.Workbook(filename)
workbook.set_properties({'created': datetime.date(2016, 4, 25)})
worksheet = workbook.add_worksheet()
worksheet.write('A1', 'Hello world')
workbook.close()
Then:
$ cmp hello1.xlsx hello2.xlsx
# No output. Files are the same.
The order in which strings are added to the file will change the layout of the sharedStrings table and thus lead to non-identical files. That is generally the case with Excel as well.
Note: This requires XlsxWriter version 1.0.4 or later to work.
Even though the author of the previous answer appears to have repudiated it, it appears to be correct, but not the whole story. I did my own tests on Python 3.7 and XlsxWriter 1.1.2. You won't notice the creation time issue if your files are small because they'll be written so fast their default creation times of "now()" will be the same.
What's missing from the first answer is that you need to make the same number of calls to the write_* methods. For example, if you call write followed by merge_range on the same cell for one of the workbooks, you need to have the same sequence of calls for the other. You can't skip the write call and just do merge_range, for instance. If you do this, the sharedStrings.xml files will have different values of count even if the value of uniqueCount is the same.
If you can arrange for these things to be true, then your two workbooks should come out as equal at the binary level.

How can I get the pos of row dynamically ? QlikView

I want to delete the rest of a loaded csv file based on the occurrence of a string.
Remove(Row, RowCnd(Interval, Pos(Top, findMeThePositionOfaGivenString('TeddyBear')),
Pos(Bottom, 1), Select(1, 0))
Or just any approach to dynamically delete a range of rows!
If you're doing this during the data import stage then I would recommend
load yourstuff
from yourfile
where index(givenstring,'Teddybear')=0;
Index will return the position of the string in the larger string.
eg. index('ABC','BC')=2 so index()=0 means the string does no exist in the searched text. Be careful of the capitalisation as it will honour that, so use upper or lower to remove that kind of confusion.
I hope I understood your request.

Asc(Chr(254)) returns 116 in .Net 1.1 when language is Hungarian

I set the culture to Hungarian language, and Chr() seems to be broken.
System.Threading.Thread.CurrentThread.CurrentCulture = "hu-US"
System.Threading.Thread.CurrentThread.CurrentUICulture = "hu-US"
Chr(254)
This returns "ţ" when it should be "þ"
However, Asc("ţ") returns 116.
This: Asc(Chr(254)) returns 116.
Why would Asc() and Chr() be different?
I checked and the 'wide' functions do work correctly: ascw(chrw(254)) = 254
Chr(254) interprets the argument in a system dependent way, by looking at the System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage property. See the MSDN article about Chr. You can check whether that value is what you expect. "hu-US" (the hungarian locale as used in the US) might do something strange there.
As a side-note, Asc() has no promise about the used codepage in its current documentation (it was there until 3.0).
Generally I would stick to the unicode variants (ending on -W) if at all possible or use the Encoding class to explicitly specify the conversions.
My best guess is that your Windows tries to represent Chr(254)="ţ" as a combined letter, where the first letter is Chr(116)="t" and the second ("¸" or something like that) cannot be returned because Chr() only returns one letter.
Unicode text should not be handled character-by-character.
It sounds like you need to set the code page for the current thread -- the current culture shouldn't have any effect on Asc and Chr.
Both the Chr docs and the Asc docs have this line:
The returned character depends on the code page for the current thread, which is contained in the ANSICodePage property of the TextInfo class. TextInfo.ANSICodePage can be obtained by specifying System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage.
I have seen several problems in VBA on the Mac where characters over 127 and some control characters are not treated properly.
This includes paragraph marks (especially in text copied from the internet or scanned), "¥", and "Ω".
They cannot always be searched for, cannot be used in file names - though they could in the past, and when tested, come up as another ascii number. I have had to write algorithms to change these when files open, as they often look like they are the right character, but then crash some of my macros when they act strangely. The character will look and act right when I save the file, but may be changed when it is reopened.
I will eventually try to switch to unicode, but I am not sure if that will help this issue.
This may not be the issue that you are observing, but I would not rule out isolated problems with certain characters like this. I have sent notes to MS about this in the past but have received no joy.
If you cannot find another solution and the character looks correct when you type it in, then I recommend using a macro snippet like the one below, which I run when updating tables. You of course have to setup theRange as the area you are looking at. A whole file can take a while.
For aChar = 1 To theRange.Characters.count
theRange.Characters(aChar).Select
If Asc(Selection.Text) = 95 And Selection.Text <> "_" Then Selection.TypeText "Ω"
Next aChar