Excel C API equivalent of Interop Range.Value in C# - excel

Trying to figure out how to read the contents of a reference and get same results and Interop/COM's Range.Value...namely that the object[,] returned contains string, DateTime, and doubles.
I'm using ExcelDNA (and underlying XlCall.Excel to call C API) and both...
ExcelReference.GetValue() and
XlCall.Excel( XlCall.xlfDeref, reference )
Both return an object[,] that is equivalent to Interop/COM's Range.Value2...namely that the object[,] returned contains only string and doubles.
The problem with this is that Dates are returned as double and I have no way of determining if the value should be a double or a DateTime.

ExcelReference.GetValue() will never return a DateTime, since that's never the stored value of a cell - it is just a display format applied to a numeric (double) value. It is similar for currency and percentage formatting.
You can read the "Contents of the cell as it is currently displayed, as text, including any additional numbers or symbols resulting from the cell's formatting." using the xlfGetCell call with the C API, using option 53. However, you then have to figure out whether the string represents a date/time yourself.
One could also read the "Number format of the cell, as text (for example, "m/d/yy" or "General")." using xlfGetCell option 7.

Related

Changing format of TODAY() in excel

I'm using today to aquire todays date and then adding a static value to the end of it using the following:
=TODAY()&"T23:00:00"
Which Returns 43202T23:00:00
I really need it in the format 2018-04-12T23:00:00
Any help on this would be great!
There are a couple ways to accomplish this, depending on whether your goal is a formatted String (to display) or a numeric value (such as data type Date) for storing or using with calculations.
If you want a formatted date/time result (to display to the user)...
Use the TEXT worksheet function:
=TEXT(TODAY(),"yyyy-mm-dd")&"T23:00:00"
...the reason this works is because TODAY() returns a Date data type, which is basically just a number representing the date/time, (where 1 = midnight on January 1, 1900, 2 = midnight on January 2, 1900, 2.5 = noon on January 2, 1900,etc).
You can convert the date type to a String (text) with the TEXT function, in whatever format you like. The example above will display today's date as 2018-04-12.
If, for example, you wanted the date portion of the string displayed asApril 12, 2018 then you would instead use:
TEXT(TODAY(),"mmmm d, yyyy")
Note that the TEXT worksheet function (and VBA's Format function) always return Strings, ready to be concatenated with the rest of the String that you're trying to add ("T23:00:00").
If you want to use the result in calculations...
If you instead want the result to be in a Date type, then instead of concatenating a string (produced by the TEXT function) to a string (from "T23:00:00"), you could instead add a date to a date:
=TODAY()+TIME(23,0,0)
or
=TODAY()+TIMEVALUE("23:00")
..and then you can format it as you like to show or hide Y/M/D/H/M/S as necessary with Number Formats (shortcut: Ctrl+1).
More Information:
MSDN : TEXT Function (Excel)
MSDN : TIMEVALUE Function (Excel)
MSDN : TIME Function (Excel)

Pandas: Calling df.loc[] from an index consisting of pd.datetime

Say I have a df as follows:
a=pd.DataFrame([[1,3]]*3,columns=['a','b'],index=['5/4/2017','5/6/2017','5/8/2017'])
a.index=pd.to_datetime(a.index,format='%m/%d/%Y')
The type of of the df.index is now
<class 'pandas.core.indexes.datetimes.DatetimeIndex'>
When we try to call a row of data based on the index of type pd.datetime, it is possible to call the value based on a string format of date instead of inputting a datetime object. In the above case, if I want to call a row of data on 5/4/2017, I can simply input the string format of the date to .loc as follows:
print(a.loc['5/4/2017'])
And we do not need to input the datetime object
print(a.loc[pd.datetime(2017,5,4)]
My question is, when calling the data from .loc based on string format of date, how does pandas know if my date string format follows m-d-y or d-m-y or other combinations? In this above case, I used a.loc['5/4/2017'] and it succeeds in returning the value. Why wouldn't it think it might mean April 5 which is not within this index?
Here's my best shot:
Pandas has an internal function called pandas._guess_datetime_format. This is what gets called when passing the 'infer_datetime_format' argument to pandas.to_datetime. It takes a string and runs through a list of "guess" formats and returns its best guess on how to convert that string to a datetime object.
Referencing a datetime index with a string may use a similar approach.
I did some testing to see what would happen in the case you described - where a dataframe contains both the date 2017-04-05 and 2017-05-04.
In this case, the following:
df.loc['5/4/2017']
Returned the Data for May 4th, 2017
df.loc['4/5/2017']
Returned the data for April 5th, 2017.
Attempting to reference 4/5/2017 in your original matrix gave an "is not in the [index]" error.
Based on this, my conclusion is that pandas._guess_datetime_format defaults to a "%m/%d/%Y" format in cases where it cannot be distinguished from "%d/%m/%Y". This is the standard date format in the US.

Changing a numeric to a string variable in Stata

I have a variable ShiftStart that is a numeric variable in the format 01jan2014 06:59:59 (and so on). I want to change this to a string variable so that I can then substring it and create variables based on just date and just time separately.
When I try
generate str20 string_shiftstart=string(ShiftStart)
I create a string but all of the cells have been converted to strange values ("1.70e+12" and so on).
How can I keep the original contents of ShiftStart when it is converted to a string?
It seems you have a variable formatted as datetime. If so, no need to convert to string. There are appropriate functions that allow you to manipulate the original variable. This is clearly explained in help datetime:
clear
set more off
*----- example data -----
set obs 5
gen double datet = _n * 100000000
format datet %tc
list
*----- what you want -----
gen double date = dofc(datet)
format %td date
gen double hour = hh(datet) + mm(datet)/60 + ss(datet)/3600
list
The reason you find your original result surprising is because you are not aware of the fact that underlying the datetime display format, is a numerical value.
A good read (aside from help datetime) is
Stata tip 113: Changing a variable's format: What it does and does not mean, The Stata Journal, by Nicholas J. Cox.
Edit
To answer your last question:
If you want to create an indicator variable marking pre/post periods, one way is using td() (see the help file). Following the example given above:
// before 04jan1960
gen pre = date < td(04jan1960)
Creating this indicator variable is not always necessary. Most commands allow the use of the if qualifier, and you can insert the condition directly. See help if.
If you mean something else, you should be more explicit.

MATLAB - Only First Letter of String is Printing

I am having an issue printing a string in MATLAB (2012a) using the fprtinf command (and sprintf).
I have an array of 12 dates (numeric). I am converting them to strings using the following command:
months = datestr(data(:,1)-365,12); %Mar13 format
I obtain the following (and desired) output when I call the months variable:
Jan12
Feb12
Mar12
Apr12
etc..
The issue is when I call the fprintf or sprintf, say with the following code:
fprintf('%s', months(1))
I will only get the first letter of the month and not the full string. Any idea how to make it print the full string?
Thanks!
The resulting data type for your months variable is an NxM character array. You need to process it as a cell array of strings instead.
dates = num2cell(data(:,1)-365)
months = cellfun(#(x) datestr(x,12),dates,'UniformOutput',false)
fprintf('%s', months{1})
should get you what you want.
Simply change your call to
fprintf('%s', months(1, :))
datestr returns the string of each of the supplied dates on a separate row.
Alternatively you could use the cellstr function to convert the result to a cell array (this would also work with non fixed-length date formats like 'dddd')
months = cellstr(months);
fprintf('%s', months{1});

Apache POI : How to format numeric cell values

I am using Apache POI 3.9 for XLS/XLSX file processing.
In the XLS sheet, there is a column with numeric value like "3000053406".
When I read it with POI with..
cell.getNumericCellValue()
It gives me value like "3.00E+08". This create huge problem in my application.
How can I set the number formatting while reading data in Apcahe POI ?
There is a way that I know is to set the column as "text" type. But I want to know if there is any other way at Apache POI side while reading the data. OR can we format it by using simple java DecimalFormatter ?
This one comes up very often....
Picking one of my past answers to an almost identical question
What you want to do is use the DataFormatter class. You pass this a cell, and it does its best to return you a string containing what Excel would show you for that cell. If you pass it a string cell, you'll get the string back. If you pass it a numeric cell with formatting rules applied, it will format the number based on them and give you the string back.
For your case, I'd assume that the numeric cells have an integer formatting rule applied to them. If you ask DataFormatter to format those cells, it'll give you back a string with the integer string in it.
Problem can be strictly Java-related, not POI related, too.
Since your call returns a double,
double val = cell.getNumericCellValue();
You may want to get this
DecimalFormat df = new DecimalFormat("#");
int fractionalDigits = 2; // say 2
df.setMaximumFractionDigits(fractionalDigits);
double val = df.format(val);
Creating a BigDecimal with the double value from the numeric cell and then using the
BigDecimal.toPlainString()
function to convert it to a plain string and then storing it back to the same cell after erasing the value solved the whole problem of exponential representation of numeric values.
The below code solved the issue for me.
Double dnum = cellContent.getNumericCellValue();
BigDecimal bd = new BigDecimal(dnum);
System.out.println(bd.toPlainString());
cellContent.setBlank();
cellContent.setCellValue(bd.toPlainString());
System.out.println(cellContent.getStringCellValue());
long varA = new Double(cellB1.getNumericCellValue()).longValue();
This will bring the exact value in variable varA.

Resources