Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Чтение данных из файлов Excel

407
15 сентября 2004 года
shupik
160 / / 15.09.2004
Возникла следующая проблема при чтении данных из файла в формате Excel: когда выполняется SQL-запрос, формат ячеек интерпретируется некорректно. То есть вместо "3" я получаю "3.0". Другими словами, детектирует драйвер неправильно. Причем, если добавить букву к этой тройке, "В3", например, все работает правильно. Вот куски кода:
CDatabase database;
CString sSql;
CString sItem1, sItem2, sItem3, sItem4,sItem5, sItem6;//переменные, в к-е пишу значения столбцов
CString sDriver;
CString sDsn;
CString sFile = "ReadExcel.xls"; //имя файла
...
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
database.Open(NULL,false,false,sDsn);

CRecordset recset( &database );
// Строка запроса
sSql = "SELECT demo_table.profile, length, diameter, height, steel, kolvo "
"FROM demo_table "
"WHERE profile='Круг' "
"ORDER BY profile";

recset.Open(CRecordset::forwardOnly,sSql,CRecordset::readOnly);
while( !recset.IsEOF() )
{
// Читаем данные
recset.GetFieldValue("profile",sItem1);
recset.GetFieldValue("length",sItem2);
recset.GetFieldValue("diameter",sItem3);
recset.GetFieldValue("height",sItem4);
recset.GetFieldValue("steel",sItem5);
CString value_steel(sItem5);
CString s;
//здесь я пытаюсь отформатировать полученные данные в текстовый формат - безуспешно
s.Format("Steel + %s",value_steel);
recset.GetFieldValue("kolvo",sItem6);
// результат: Steel + 3.0, а должно быть - Steel + 3
// Добавляем в список результаты
(void)m_ctrlSortList.AddItem( _T(sItem1), _T(sItem2), _T(sItem3), _T(sItem4), _T(s), _T(sItem6) );


Есть у кого-нибудь соображения по этому поводу? Может быть, кто-то сталкивался с такой ерундой?
6.6K
22 сентября 2004 года
hunter
46 / / 22.09.2004
Цитата:
Originally posted by shupik
Возникла следующая проблема при чтении данных из файла в формате Excel: когда выполняется SQL-запрос, формат ячеек интерпретируется некорректно. То есть вместо "3" я получаю "3.0". Другими словами, детектирует драйвер неправильно. Причем, если добавить букву к этой тройке, "В3", например, все работает правильно. Вот куски кода:
CDatabase database;
CString sSql;
CString sItem1, sItem2, sItem3, sItem4,sItem5, sItem6;//переменные, в к-е пишу значения столбцов
CString sDriver;
CString sDsn;
CString sFile = "ReadExcel.xls"; //имя файла
...
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
database.Open(NULL,false,false,sDsn);

CRecordset recset( &database );
// Строка запроса
sSql = "SELECT demo_table.profile, length, diameter, height, steel, kolvo "
"FROM demo_table "
"WHERE profile='Круг' "
"ORDER BY profile";

recset.Open(CRecordset::forwardOnly,sSql,CRecordset::readOnly);
while( !recset.IsEOF() )
{
// Читаем данные
recset.GetFieldValue("profile",sItem1);
recset.GetFieldValue("length",sItem2);
recset.GetFieldValue("diameter",sItem3);
recset.GetFieldValue("height",sItem4);
recset.GetFieldValue("steel",sItem5);
CString value_steel(sItem5);
CString s;
//здесь я пытаюсь отформатировать полученные данные в текстовый формат - безуспешно
s.Format("Steel + %s",value_steel);
recset.GetFieldValue("kolvo",sItem6);
// результат: Steel + 3.0, а должно быть - Steel + 3
// Добавляем в список результаты
(void)m_ctrlSortList.AddItem( _T(sItem1), _T(sItem2), _T(sItem3), _T(sItem4), _T(s), _T(sItem6) );

Слушай а есть такая необходимость работать с Excel Через ODBC? Есть прекрасная возможность все это сделать с помощью #import ...Если хочешь ссылку найду.

Есть у кого-нибудь соображения по этому поводу? Может быть, кто-то сталкивался с такой ерундой?

:-?

407
22 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by hunter
:-?


Кинь ссылку на #import, если не затруднит. Кстати, такой метод решает эту проблему - я имею ввиду считывание столбца как данных целого типа?

1.2K
23 сентября 2004 года
Kalitkin
108 / / 05.03.2004
Цитата:
Originally posted by shupik
Возникла следующая проблема при чтении данных из файла в формате Excel: когда выполняется SQL-запрос, формат ячеек интерпретируется некорректно. То есть вместо "3" я получаю "3.0". Другими словами, детектирует драйвер неправильно. Причем, если добавить букву к этой тройке, "В3", например, все работает правильно. Вот куски кода:
CDatabase database;
CString sSql;
CString sItem1, sItem2, sItem3, sItem4,sItem5, sItem6;//переменные, в к-е пишу значения столбцов
CString sDriver;
CString sDsn;
CString sFile = "ReadExcel.xls"; //имя файла
...
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
database.Open(NULL,false,false,sDsn);

CRecordset recset( &database );
// Строка запроса
sSql = "SELECT demo_table.profile, length, diameter, height, steel, kolvo "
"FROM demo_table "
"WHERE profile='Круг' "
"ORDER BY profile";

recset.Open(CRecordset::forwardOnly,sSql,CRecordset::readOnly);
while( !recset.IsEOF() )
{
// Читаем данные
recset.GetFieldValue("profile",sItem1);
recset.GetFieldValue("length",sItem2);
recset.GetFieldValue("diameter",sItem3);
recset.GetFieldValue("height",sItem4);
recset.GetFieldValue("steel",sItem5);
CString value_steel(sItem5);
CString s;
//здесь я пытаюсь отформатировать полученные данные в текстовый формат - безуспешно
s.Format("Steel + %s",value_steel);
recset.GetFieldValue("kolvo",sItem6);
// результат: Steel + 3.0, а должно быть - Steel + 3
// Добавляем в список результаты
(void)m_ctrlSortList.AddItem( _T(sItem1), _T(sItem2), _T(sItem3), _T(sItem4), _T(s), _T(sItem6) );


Есть у кого-нибудь соображения по этому поводу? Может быть, кто-то сталкивался с такой ерундой?



да забей ты на все, напиши
s.Format("Steel + %d",(int)atoi(value_steel)); :)

слушай, а ты не мог бы поподробнее написать строку конекта к exel

6.6K
23 сентября 2004 года
hunter
46 / / 22.09.2004
Цитата:
Originally posted by shupik

Кинь ссылку на #import, если не затруднит. Кстати, такой метод решает эту проблему - я имею ввиду считывание столбца как данных целого типа?



shupik лови:
http://www.rusdoc.ru/material/lang/cpp/import.shtml

P.S. Там сверху всякая лабудень идет, а потом ниже про MS Excel. Не забудь файлик office.h создать (в зависимости от версии офиса)
Ну и далее разберешься, если чего пиши!
CoInitialize(NULL);
try
{
using namespace Excel;
_ApplicationPtr excel("Excel.Application");

_WorkbookPtr book = excel->Workbooks->Open(_bstr_t(имя файла xls));
//Книга №1
_WorksheetPtr sheet = book->Worksheets->Item[1L];
LONG i;
//к примеру читаешь целое из ячейки A1
i = LONG(sheet->Range["A1"]->Value);
}
catch (_com_error& er)
{
}
CoUninitialize();

407
23 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by Kalitkin


да забей ты на все, напиши
s.Format("Steel + %d",(int)atoi(value_steel)); :)

слушай, а ты не мог бы поподробнее написать строку конекта к exel


По поводу коннекта к Excel:

CDatabase database;
sDriver = GetExcelDriver();
if( sDriver.IsEmpty() )
{
// Драйвер не был установлен
AfxMessageBox("No Excel ODBC driver found");
return;
}

CString sSql;
CString sItem1, sItem2, sItem3, sItem4,sItem5, sItem6;//переменные, в к-е пишу значения столбцов
CString sDriver;
CString sDsn;
CString sFile = "ReadExcel.xls"; //имя файла
...
sDsn.Format("ODBC;DRIVER={%s};DSN='';DBQ=%s",sDriver,sFile);
database.Open(NULL,false,false,sDsn);
//А это собственно метод чтения драйвера
CString CExcelAutomatizationDlg::GetExcelDriver()
{
char szBuf[2001];
WORD cbBufMax = 2000;
WORD cbBufOut;
char *pszBuf = szBuf;
CString sDriver;
//получаем имена установленных драйверов ("odbcinst.h" должен быть подключен)
if(!SQLGetInstalledDrivers(szBuf,cbBufMax,& cbBufOut))
return "";

// Ищем драйвер...
do
{
if( strstr( pszBuf, "Excel" ) != 0 )
{
// Нашли...
sDriver = CString( pszBuf );
break;
}
pszBuf = strchr( pszBuf, '\0' ) + 1;
}
while( pszBuf[1] != '\0' );

return sDriver;
}
Спасибо за подсказку. А как решить обратную задачу - выложить в ячейки вновь созданного листа Excel числа в задаваемом формате? Я поступил примерно так:
COleSafeArray sa;
for(lRow=0;lRow<=amount_of_records-1;lRow++)
{
CString value_profile,
value_x1,
value_x2,
value_length,
value_diameter,
value_height,
value_steel,
value_kolvo;

index[0] = lRow;

// заполняем первый столбец номерами позиций
index[1] = 0;
lNumber=lRow+1;
sa.PutElement(index, COleVariant(lNumber));
// второй столбец заполняем наименованием профиля (Круг, Квадрат и т.д.)
index[1] = 1;
//забираем данные из массива значений профилей
value_profile=aMyProfileValues.GetAt(lRow);
//"кладем" их в OLE-массив
sa.PutElement(index, (COleVariant)value_profile);

index[1]=2;
value_length=aMyLengthValues.GetAt(lRow);
sa.PutElement(index, (COleVariant)value_length);

index[1]=3;
value_x1=aMyFirstFieldValues.GetAt(lRow);
sa.PutElement(index, (COleVariant)value_x1);
Проблема в том, что второй параметр функции PutElement подразумевает тип данных COleVariant, а мне нужно вывести как в виде строки, так и в виде float. Извини за столь подробное описание, но я уже с ного сбился в поисках правильного решения этой задачи...

407
23 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by hunter


shupik лови:
http://www.rusdoc.ru/material/lang/cpp/import.shtml

P.S. Там сверху всякая лабудень идет, а потом ниже про MS Excel. Не забудь файлик office.h создать (в зависимости от версии офиса)
Ну и далее разберешься, если чего пиши!
CoInitialize(NULL);
try
{
using namespace Excel;
_ApplicationPtr excel("Excel.Application");

_WorkbookPtr book = excel->Workbooks->Open(_bstr_t(имя файла xls));
//Книга №1
_WorksheetPtr sheet = book->Worksheets->Item[1L];
LONG i;
//к примеру читаешь целое из ячейки A1
i = LONG(sheet->Range["A1"]->Value);
}
catch (_com_error& er)
{
}
CoUninitialize();


Спасибо - попробую. Тут еще больше задача усложнилась: теперь нужно на ходу анализировать, какого типа число в столбце. Если вида 25.0, то дробную часть отрезать, если вида 3.7 - оставить. Это я выполнил, вопрос в другом - как во вновь созданный лист Excel занести данные в формате float? Дело в том, что я применил для заполнения ячеек значениями класс COleSafeArray. И вроде бы даже все работает :-) Но есть один досадный ляп - при вызове функции PutElement нужно в качестве параметра передавать тип значения СOleVariant, а такой тип совместим только с CString. Вот кусок кода:
COleSafeArray sa;
for(lRow=0;lRow<=amount_of_records-1;lRow++)
{
CString value_profile,
value_x1,
value_x2,
value_length,
value_diameter,
value_height,
value_steel,
value_kolvo;

index[0] = lRow;

// заполняем первый столбец номерами позиций
index[1] = 0;
lNumber=lRow+1;
sa.PutElement(index, COleVariant(lNumber));
// второй столбец заполняем наименованием профиля (Круг, Квадрат и т.д.)
index[1] = 1;
value_profile=aMyProfileValues.GetAt(lRow);
sa.PutElement(index, (COleVariant)value_profile);

index[1]=2;
value_length=aMyLengthValues.GetAt(lRow);
sa.PutElement(index, (COleVariant)value_length);

index[1]=3;
value_x1=aMyFirstFieldValues.GetAt(lRow);
sa.PutElement(index, (COleVariant)value_x1);
То есть, если число целое - все заполняется без проблем, а если дробное - ерунда какая-то начинается. Ну, например, 26.8 вносится как "26 августа". Или просто вот так: 34.5 (а мне нужно 34,5 - иначе ячейки не суммируются потом). Может, подскажешь, в чем тут дело?

368
23 сентября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by shupik

26.8 вносится как "26 августа". Или просто вот так: 34.5 (а мне нужно 34,5 - иначе ячейки не суммируются потом). Может, подскажешь, в чем тут дело?


нужно установить формат ячейки. он теперь general.

407
23 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by rostyslav

нужно установить формат ячейки. он теперь general.


Будь так добр - объясни, пожалуйста, на пальцах, как устанавливается формат ячеек Excel. Это какой-то дополнительный метод класса COleSafeArray? Или класса CRange?

368
23 сентября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by shupik

Будь так добр - объясни, пожалуйста, на пальцах, как устанавливается формат ячеек Excel. Это какой-то дополнительный метод класса COleSafeArray? Или класса CRange?



пока еще, я выбирал данные из Excel, сохранив их в txt, или в dbf3 формат.(1С с другим форматом работать не умеет).

в Excele

Selection.NumberFormat = "$#.##0,00"

Класс CRange должен бы иметь property NumberFormat.

407
23 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by rostyslav


пока еще, я выбирал данные из Excel, сохранив их в txt, или в dbf3 формат.(1С с другим форматом работать не умеет).

в Excele

Selection.NumberFormat = "$#.##0,00"

Класс CRange должен бы иметь property NumberFormat.


Все, с этим разобрался. По крайней мере, с числовыми данными. Вот так:
index[1]=12;
value_kolvo=aMyKolvo.GetAt(lRow);
double d=atof(value_kolvo);
sa.PutElement(index, (COleVariant) d);
А теперь небольшой вопрос немного не по теме: как получить дату из встроенного календаря VC++ 6.0? Там есть метод: OnGetdaystateMonthcalendar(NMHDR* pNMHDR, LRESULT* pResult)
А я хочу получить из него выбранную дату. Как и что нужно здесь вписать?
Заранее благодарен.

368
23 сентября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by shupik

как получить дату из встроенного календаря VC++ 6.0?


лучше определи переменную типа Control на основе этого календаря, m_cal(напр.) и

SYSTEMTIME st;

m_cal.GetCurSel(&st);

407
23 сентября 2004 года
shupik
160 / / 15.09.2004
Цитата:
Originally posted by rostyslav

лучше определи переменную типа Control на основе этого календаря, m_cal(напр.) и

SYSTEMTIME st;

m_cal.GetCurSel(&st);


Выполнил. Только не пойму, как вытащить собственно дату из m_cal. У меня следующая ситуация:
COleDateTime vDateTime;
vDateTime.SetDate(2004,9,18);
Это я, так сказать, принудительно вручную выставляю дату. Потом vDateTime используется для установки значения даты в ячейку Excel. То есть тип должен быть COleDateTime. Вот как их пересечь между собой - m_cal и vDateTime? Привести к одному типу?

368
23 сентября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by shupik

Вот как их пересечь между собой - m_cal и vDateTime? Привести к одному типу?


у ф-ии getCurSel есть 3 формата(MSDN).

BOOL GetCurSel( COleDateTime& refDateTime ) const;

BOOL GetCurSel( CTime& refDateTime ) const;

BOOL GetCurSel( LPSYSTEMTIME pDateTime ) const;

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог