Чтение данных из файлов Excel
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: когда выполняется 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 ...Если хочешь ссылку найду.
Есть у кого-нибудь соображения по этому поводу? Может быть, кто-то сталкивался с такой ерундой?
:-?
:-?
Кинь ссылку на #import, если не затруднит. Кстати, такой метод решает эту проблему - я имею ввиду считывание столбца как данных целого типа?
Возникла следующая проблема при чтении данных из файла в формате 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
Кинь ссылку на #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();
да забей ты на все, напиши
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. Извини за столь подробное описание, но я уже с ного сбился в поисках правильного решения этой задачи...
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 - иначе ячейки не суммируются потом). Может, подскажешь, в чем тут дело?
26.8 вносится как "26 августа". Или просто вот так: 34.5 (а мне нужно 34,5 - иначе ячейки не суммируются потом). Может, подскажешь, в чем тут дело?
нужно установить формат ячейки. он теперь general.
нужно установить формат ячейки. он теперь general.
Будь так добр - объясни, пожалуйста, на пальцах, как устанавливается формат ячеек Excel. Это какой-то дополнительный метод класса COleSafeArray? Или класса CRange?
Будь так добр - объясни, пожалуйста, на пальцах, как устанавливается формат ячеек Excel. Это какой-то дополнительный метод класса COleSafeArray? Или класса CRange?
пока еще, я выбирал данные из Excel, сохранив их в txt, или в dbf3 формат.(1С с другим форматом работать не умеет).
в Excele
Selection.NumberFormat = "$#.##0,00"
Класс CRange должен бы иметь property NumberFormat.
пока еще, я выбирал данные из 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)
А я хочу получить из него выбранную дату. Как и что нужно здесь вписать?
Заранее благодарен.
как получить дату из встроенного календаря VC++ 6.0?
лучше определи переменную типа Control на основе этого календаря, m_cal(напр.) и
SYSTEMTIME st;
m_cal.GetCurSel(&st);
лучше определи переменную типа Control на основе этого календаря, m_cal(напр.) и
SYSTEMTIME st;
m_cal.GetCurSel(&st);
Выполнил. Только не пойму, как вытащить собственно дату из m_cal. У меня следующая ситуация:
COleDateTime vDateTime;
vDateTime.SetDate(2004,9,18);
Это я, так сказать, принудительно вручную выставляю дату. Потом vDateTime используется для установки значения даты в ячейку Excel. То есть тип должен быть COleDateTime. Вот как их пересечь между собой - m_cal и vDateTime? Привести к одному типу?
Вот как их пересечь между собой - m_cal и vDateTime? Привести к одному типу?
у ф-ии getCurSel есть 3 формата(MSDN).
BOOL GetCurSel( COleDateTime& refDateTime ) const;
BOOL GetCurSel( CTime& refDateTime ) const;
BOOL GetCurSel( LPSYSTEMTIME pDateTime ) const;