Answer the question
In order to leave comments, you need to log in
How to change the data format transmitted from Excel?
I am writing a program that works with an Excel file.
The task is to read its contents and write it to an array.
Everything works, but some of the data is distorted when writing to the array. When reading from a particular column.
For example - Excel in the file (in the column) says 6651440820000450, and the array receives the value 6.67716087900069E+15.
In Excel in a file, the cells in this column are of type numeric.
Moreover, other similar cells containing less long numbers are written to the array correctly, without distortion.
How to fix it?
Part of the code
var
Ap:Variant; //Переменная excel файла
TABLE_list_1 : array of array [1..50] of string; //Массив
begin
Ap:=CreateOleObject('Excel.Application'); //Создаем объект
Ap.Workbooks.Open(input_file_path,0,True); //Открываем файл для чтения
Ap.DisplayAlerts:=False; //Отключаем любые сообщения excel
SetLength(TABLE_list_1, 1000000); //Указываем размер массива
//Он не динамический т.к. в Delphi 7 есть ошибка при больших динамических массивах
//Передаем содержимое ячейки Excel в элемент массива
for i:=1 to 50 do
begin
for j:=1 to 50 do
begin
TABLE_list_1[TABLE_list_1_records_count,j]:=Ap.Cells[i,TABLE_list_1_column_number[j]];
end;
end;
Ap.Application.Quit; //Закрываем excel файл
Answer the question
In order to leave comments, you need to log in
Swimming, we know. The array receives just what is needed. The reason is in the number → string conversion algorithms, and you need to add this thing:
“If the number is of type Double, in fact an exact integer and is within certain limits, convert it to Int64, and then Int64 to a string.”
The very test to see if double is an exact integer is rather tricky. I have code for this in C++ (which in turn is a port of code from Java). Will you port to Delphi yourself?
enum {
DOUBLE_MANTISSA_BITS = 52,
DOUBLE_MIN_EXPONENT = -1022,
DOUBLE_EXPONENT_BIAS = 1023,
};
#define UC8x(X,Y,Z,T) (static_cast<uint64_t>(0x##X##Y##Z##T##ULL))
#define DOUBLE_MANTISSA_MASK UC8x(000f, ffff, ffff, ffff)
#define DOUBLE_EXPONENT_MASK UC8x(7ff0, 0000, 0000, 0000)
#define DOUBLE_EXPONENT_MASK_HI UC4x(7ff0, 0000)
#define DOUBLE_IMPLICIT_BIT (DOUBLE_MANTISSA_MASK + 1)
union DoubleInt {
double asDouble;
uint64_t asInt;
struct {
uint32_t lo, hi;
} asIntel;
....
}
int DoubleInt::exponent() const
{
return static_cast<int>((
static_cast<int64_t>(asInt & DOUBLE_EXPONENT_MASK) >>
(DOUBLE_MANTISSA_BITS)) - DOUBLE_EXPONENT_BIAS);
}
uint64_t DoubleInt::unsafeMantissa() const
{
int ex = exponent();
uint64_t bits = asInt & DOUBLE_MANTISSA_MASK;
return (ex == DOUBLE_MIN_EXPONENT - 1)
? bits << 1
: bits | DOUBLE_IMPLICIT_BIT;
}
bool DoubleInt::isPreciseInteger() const
{
// функцию isFinite() намеренно упустил, ибо она есть «в коробке» Delphi.
// А вот в Си++ есть не во всех реализациях…
return isFinite()
&& (asDouble == 0.0 ||
DOUBLE_MANTISSA_BITS - numberOfTrailingZeros(unsafeMantissa()) <= exponent());
}
int math::numberOfTrailingZeros(uint64_t i)
{
uint32_t x, y;
if (i == 0u) return 64;
int n = 63;
y = static_cast<uint32_t>(i);
if (y != 0) { n = n -32; x = y; } else x = (int)(i >> 32);
y = x << 16; if (y != 0) { n = n -16; x = y; }
y = x << 8; if (y != 0) { n = n - 8; x = y; }
y = x << 4; if (y != 0) { n = n - 4; x = y; }
y = x << 2; if (y != 0) { n = n - 2; x = y; }
return n - ((x << 1) >> 31);
}
bool math::isPreciseInteger(double x)
{
DoubleInt di;
di.asDouble = x;
return di.isPreciseInteger();
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question