Format cell data type when data added with worksheet.add_table - xlsxwriter

First, love xlsxwriter. Use both python and perl modules. Thanks so much to John M.
When creating a table using add_table(), all the data cells get data formatted as text. Even if only integers in the data. An integer view as text causes a small green triangle to appear in the upper left of each cell viewed in Excel.
Is there anyway to go back and modify cell data types after adding data with add_table??
Here is the tidbit of code doing the add_table() :
worksheet = self.add_worksheet(name)
worksheet.header = header
tableinfo= {
'data' : data,
'columns' : columns
}
lastcol = scol + (len(header) - 1)
lastrow = srow + len(data)
worksheet.add_table(srow,scol,lastrow,lastcol,tableinfo)

When creating a table using add_table(), all the data cells get data formatted as text. Even if only integers in the data.
That shouldn't be the case. The add_table() method uses the write() method which writes the correct Excel data type based on the Python data type.
You can see that it works as expected using the table example in the docs.
So, if you are seeing green warning triangle it is probably because you have numeric data stores as strings in your Python code.
If you convert your sample code to a working example we could verify that.

Related

cannot get value from a cell in libreoffice 6.4.3.2 basic

I am new to libreoffice basic, i have experience with VBA but this libreoffice is different.
I just want to get cell value but it always return zero value to me while the actuall cell can be text or number.
Here is a partial of my simple code.
Sub test_moved()
Dim Doc As Object
'worksheet
Dim sh_village As Object
Dim sh_cbc As Object
sh_village = ThisComponent.CurrentController.getActiveSheet()
'sh_village = Doc.Sheets.getByName("VillageFinal")
'sh_village = Doc.Sheets(1)
Msgbox(sh_village.getCellrangeByName("B2").getValue())
Msgbox(sh_village.getCellrangeByName("B2").Value)
Msgbox(sh_village.getCellByPosition(1,1).Value)
msgbox("The process is completed.")
End Sub
Do we need to do prior task before start coding?
The code works correctly for numeric values. However, for strings, including strings that look like a number, it will display 0 because there is no numeric value.
What you probably want instead is:
MsgBox(sh_village.getCellRangeByName("B2").getString())
Also check out Format -> Cells -> Number to see how the data is displayed in the cell. And be on the lookout for a single quote at the front of the value in the formula bar (for example '42), because that means it is a string. Delete the quote to make it a number.
i have experience with VBA but this libreoffice is different.
Yes, LibreOffice Basic is a different language from VBA and the LibreOffice API is very different from the MS Office API. Knowing that will help you use it more effectively. If possible, avoid Option Compatible, because it won't fix most problems and will only muddy the waters.

Google Script Sheets API - default number format

It looks like google sheets is making the same mistake as Excel, by "thinking ahead" and converting the value "1.1.1" to 2001.01.01 when doing sheet.appendRow. I have tried to set the number format of the column in charge to "#" (which should be plain text) before inserting rows - but looks ineffective. On the other hand doing the same after inserts is also ineffective, as the content is already "date".
Adding ' before is working, but it is not what I need.
Is there any way to give a default format or to disable such automatic conversion (from google script)?
I have a cell in which a form deposits a variable number of values seperated by a comma such as: " 1, 2, 4, 6 " etc - when there are only three answers, Google "helps" me by converting the value into a date object. But it's supposed to be a list of choices...
It's not pretty, but I've managed a workaround by using .getDisplayValue instead of .getValue - it does change the cell value into a string, so if you need to do further manipulations that are dependent on the value being a number or something, obviously, this fails.
I overwrite the value for the problem cell in my array before passing it to .appendRow
//getting the values
var values = s.getRange(row,1,1,lastCol).getValues()[0];
//brute force crushing of problem value
values[5] = s.getRange(row,6).getDisplayValue();

grab and filter from more than 255 columns from a huge closed workbook

i have a huge workbook (0.6 million rows) and 315 columns whose column names i need to grab into an array. due to the huge size, i don't want to open and close the workbook to copy the 1st row of the range. Also, I want to only grab certain columns from the 1st row that begin with the word "Global ".
can anyone help with short code example on how to go about doing this? please note i have tried ADOX, ADO etc but both show the 255 column limitations. I also dont want to open the workbook, but pull the required "Global " columns from the 315 columns into an array.
any help is most appreciated.
You can copy the first row of your target by opening a new workbook, and in A1 use this formula:
='C:\PATH_TO_TARGET\[TARGET_FILE_NAME.xlsx]WORKSHEET_NAME'!A1
Note that PATH+FILENAME+WORKSHEET is enclosed in single quotes, the FILENAME is enclosed in square brackets, and an exclamation separates the cell reference.
Then copy/Paste or fill right to get the next 314 columns. Note: this formula will return zero for empty target cells.
Once you have the column heading you can copy/paste_special_values if you want to destroy the links to the closed workbook.
Hope that helps
You could use the Python programing language.
While it does not actively works with XLSX fiels, you just have to install the openpyxl external module from here: https://pypi.python.org/pypi/openpyxl -
(You will also have to install Python. of course - just download it from www.python.org)
It will make working with your data in an interactive Python session a piece of cake, and the time to open the workbook without having to load the Excel interface should be a fraction of what you are expecting. (I think it will have to fit in your memory, though).
But this is all I had to type, in an interactive Python2 session to open a workbook, and retreive the column names that start with "bl":
import openpyxl
a = openpyxl.load_workbook("bla.xlsx")
[cell.value for cell in a.worksheets[0].rows[0] if cell.value.startswith("bl")]
output:
Out[8]: [u'bla', u'ble', u'bli', u'blo', u'blu']
The last input line requires on to know Python to be understood, so, here is a summary of what happens: Python is a language very fond of working with sequences - and the openpyxl libray gives your workbook as just that:
an object which is a sequence of worksheets - each worksheet having a rows attribute which has a sequence of all rows in the sheet, and each row bein a sequence of cells. Each cell has a value attribute which is the text within it.
The inline for statement is the compact form, but it could be written as a multiple line statement as:
In [10]: for cell in a.worksheets[0].rows[0]:
....: if cell.value.startswith("bl"):
....: print cell.value
....:
bla
ble
bli
blo
blu
Keep in mind that by exploring Python a bit deeper, you can programatically manipulate your data in a way that will be easier than ininteractivelygiven a data-set this size - and you can even use Python itself to drop select contents to an SQL database, (including its bult-in, single-file database, sqlite), where sophisticated indexes and queries can make working with your data a breeze)

How can I convert columns into a single, pipe-separated column without losing scientific notation?

I have used this VBA code to convert columns into pipe separated format. However, the data contains numbers in scientific notation (eg 2.000000e-01) which Excel automatically converts into 0.2 which I don't want.
I have tried changing this code:
var = Application.Transpose(Application.Transpose(rng.Value))
into
var = Application.Transpose(Application.Transpose(rng))
or even
var = Application.Transpose(Application.Transpose(rng.Text))
neither of which work. I've also tried formatting the cells all to Text (the macro then gives a Value error) or even switching off scientific notation.
How can I convert columns into a single, pipe-separated column without losing scientific notation?
Sample columns:
SAMPLE TEST 2.000000e-01 2.000000e-01
You want to concatenate text values using either the CONCATENATE function or the & operator. For the scientific notation, you want to use the TEXT function. Excel is actually storing the numbers as 0.2 but then displaying them in scientific notation.
The help for the TEXT function says:
Syntax: TEXT(value, format_text)
Display scientific notations:
To display numbers in scientific (exponential) format, use the following exponent codes in the format_text argument.E (E-, E+, e-, e+) Displays a number in scientific (exponential) format. Excel displays a number to the right of the "E" or "e" that corresponds to the number of places that the decimal point was moved. For example, if the format_text argument is "0.00E+00", Excel displays the number 12,200,000 as 1.22E+07. If you change the format_text argument to "#0.0E+0", Excel displays 12.2E+6.
So for your example, assuming the values are in cells A1:D1, use:
=A1&"|"&B1&"|"&TEXT(C1,"0.000000E+00")&"|"&TEXT(D1,"0.000000E+00")
Or in VBA, you can use the Text property of the Range object to get the contents of the cell as they are displayed. If the column width is too narrow for a date and the column shows "########" then that is what the Text property will return.
EDIT: I misread the post. This answer is for separating text from one column into many columns. OP is trying the reverse.
You use the Excel Text to Columns wizard (on the Data tab, select Text to Columns). Select your data, then run click the menu. When you get to step 3, tell Excel that you want to keep the column as Text.
If you need this done using VBA, then use the macro recorder to get the initial code which you can then tweak to fit your needs.

Column references in formulas

I am a little stuck at the moment. I am working on an array of data and need to find a way to input column numbers into formulas.
-I have used the match function to find the corresponding column number for a value.
ex. "XYZ" matched with Column 3, which is equivalent to C1:Cxxxxxx
-now for inputing the C1:Cxxxxxx into a formula to get data for that particular column, I would like to be able to directly reference the Column 3 part, because I plan on using this workbook in the future and the column needed to run the calculation may or may not be column 3 the next time I use it.
- is there any way to tell excel to use a formula to tell excel which column to use for an equation?
so a little more detail, I have the equation
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
instead of specifying to use column C, is there a way to use a formula to tell it to use C?
EDIT: more additional info;
"i am basically running the equivalent of a SQL where statement where foo and bar are true, I want excel to spit out a concatenated list of all baz values where foo and bar are true. ideally i would like it to ONLY return baz values that are true, then I will concat them together separately. the way I got it now, the expression will test every row separately to see if true; if there is 18K rows, there will be 18K separate tests.. it works, but it's not too clean. the goal is to have as much automated as possible. *i do not want to have to go in and change the column references every time I add a new data arra*y"
Thanks
You can use INDEX, e.g. if you have 26 possible columns from A to Z then this formula will give you your column C range (which you can use in another formula)
=INDEX(Sheet3!$A$1:$Z$250000,0,3)
The 0 indicates that you want the whole column, the 3 indicates which column. If you want the 3 can be generated by another formula like a MATCH function
Note: be careful with AND in
=AND(Sheet3!$C$1:$C$250000=$A$4,Sheet3!$B$1:$B$250000=$B$4)
AND only returns a single result not an array, if you want an array you might need to use * like this
=(Sheet3!$C$1:$C$250000=$A$4)*(Sheet3!$B$1:$B$250000=$B$4)
You could use ADDRESS to generate the text, you then need to use INDIRECT as you are passing a string rather than a range to the fomula
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,INDIRECT(ADDRESS(1,2,,,"Sheet3") & ":" & ADDRESS(250000,2))=$B$4)
Obviously replace the 3s and 2s in the ADDRESS formulae with your MATCH function you used to get the column number. The above assumes the column for $B$1:$B$25000 is also found using `MATCH', otherwise it is just:
=AND(INDIRECT(ADDRESS(1,3,,,"Sheet3") & ":" & ADDRESS(250000,3))=$A$4
,Sheet3!$B$1:$B$25000=$B$4)
Note a couple of things:
You only need to use "Sheet3" on the first part of the INDRECT
Conditions 3 and 4 in the ADDRESS formula are left as default, this
means they return absolute ($C$1) reference and are A1 style as
opposed to R1C1
EDIT
Given the additional info maybe using an advanced filter would get you near to what you want. Good tutorial here. Set it up according to the tutorial to familiarise yourself with it and then you can use some basic code to set it up automatically when you drop in a new dataset:
Paste in the dataset and then use VBA to get the range the dataset uses then apply the filter with something like:
Range("A6:F480").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
Sheets("Sheet1").Range("A1:B3"), Unique:=False
You can also copy the results into a new table, though this has to be in the same sheet as the original data. My suggestion would be paste you data into hidden columns to the left and put space for your criteria in rows 1:5 of the visible columns and then have a button that gets the used range for your data, applies the filter and copies the data below the criteria:
Range("A6:F480").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Sheets _
Range("H1:M3"), CopyToRange:=Range("H6"), Unique:=False
Button would need to clear the destination cells first etc, make sure you have enough hidden columns etc but it's all possible. Hope this helps.