#import библиотеки в зависимости от версии Excel

Автор Тема: #import библиотеки в зависимости от версии Excel  (Прочитано 12134 раз)

0 Пользователей и 3 Гостей просматривают эту тему.

Оффлайн ParavozzzАвтор темы

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Добрый день!
В своём arx-приложении экспортирую в Excel данные. Сейчас всё настроено под Excel 2013.
Код - C++ [Выбрать]
  1. #import "C:\\Program Files\\Common Files\\microsoft shared\\OFFICE15\\MSO.DLL"
  2. #import "C:\\Program Files\\Microsoft Office\\OFFICE15\\EXCEL.EXE"

Как загрузить библиотеку в зависимости от версии Excel?

Предварительно узнав версию, например в реестре. Для того, что бы можно было работать с разными версиями Excel.

Нашел, что-то похожее в этом топике Работа с Word/Excel через Ole/иные способы, но не могу понять что это за параметры:
Код - C++ [Выбрать]
  1. #ifdef MSO2000
  2. #ifdef MSO2002
  3. #ifdef MSO2003
  4. #ifdef MSOXP
Автор пишет, что это препроцессорные константы, в настройках проекта.
Заранее благодарен!

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Как загрузить библиотеку в зависимости от версии Excel?
Зачем? Если хочешь не зависеть от версии Excel, то тогда так: https://docs.microsoft.com/en-us/office/troubleshoot/office-developer/automate-excel-from-c
Нашел, что-то похожее в этом топике Работа с Word/Excel через Ole/иные способы, но не могу понять что это за параметры:
Это не поможет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Как загрузить библиотеку в зависимости от версии Excel?
если не секрет, а зачем?
Автор пишет, что это препроцессорные константы, в настройках проекта.
это вообще черезжо странный вариант. это значит, что у автора установлено несколько экселей и в зависимости от того, библиотека какого экселя ему нужна, тот #define он и пишет ручками. например, хочется пользоваться библиотекой 2003 офиса, он печатает где-то (например, в stdafx.h #define MSO2003) и компилит проект. в итоге подтягиваются в исполнительный файл все используемые точки входа из указанной либины (это если так, на пальцах).

PS: из своего опыта, уже лет... да уже больше 20-ти, выводим информацию и в ворд и в эксель. информация стандартная, таблички, тексты, формулы. так вот. пользователи наши есть еще и с 97-м офисом (работает и полностью устраивает :) ). итого, чтоб не изобретать велосипед, за основу взяли "olb" минимально допустимого офиса. во всех остальных офисах точки входа и функции остались теми же. да, новых наворотов нет из-за старого olb-файла, но нам они и не нужны.
Код - C++ [Выбрать]
  1. #import "EXCEL8.OLB" auto_search auto_rename
вот этого достаточно для того, чтоб создать экселевский документ в MSExcel начиная с 97 до текущего (в зависимости от того, какой установлен у пользователя), в нем кучу страниц, и в каждую вывести кучу разграфленных таблиц с разными границами хоть для каждой группы ячеек, раскрашенных, сгруппированных и с формулами. графики тоже можно, но нет необходимости. ну и разрядность тож роли не играет. работает и в win32 и в x64.
Да, сам OLB должен лежать по пути доступа lib-файлов

Оффлайн ParavozzzАвтор темы

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
если не секрет, а зачем?
Что бы не зависеть от версии офиса и от конкретного пути расположения импортируемой библиотеки. Сейчас получается что у меня жестко задан путь к импортируемой библиотеке и не факт, что у пользователя он такой же.

Код - C++ [Выбрать]
  1. #import "EXCEL8.OLB" auto_search auto_rename
вот этого достаточно для того, чтоб создать экселевский документ в MSExcel начиная с 97 до текущего
Николай, правильно ли я понимаю, что достаточно где-то найти EXCEL8.OLB, импортировать его, скомпилировать .ARX, и ARX-приложению будет не важно какой у пользователя установлен Excel и есть ли у него на компьютере  файл EXCEL8.OLB?
Таблицы у меня совсем простые (формулы суммы, округления и объединение ячеек в заголовках таблицы).

Зачем? Если хочешь не зависеть от версии Excel, то тогда так: https://docs.microsoft.com/en-us/office/troubleshoot/office-developer/automate-excel-from-c
Александр, спасибо, попробую с этим тоже разобраться.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Николай, правильно ли я понимаю, что достаточно где-то найти EXCEL8.OLB, импортировать его, скомпилировать .ARX, и ARX-приложению будет не важно какой у пользователя установлен Excel и есть ли у него на компьютере  файл EXCEL8.OLB?
Таблицы у меня совсем простые (формулы суммы, округления и объединение ячеек в заголовках таблицы).
Да. Единственно что сохранение там (если не изменяет память) в формат xls, а не xlsx.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн ParavozzzАвтор темы

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
А можно попросить небольшой фрагмент кода для работы с EXCEL8.OLB?

На данный момент у меня реализовано следующим образом:
Код - C++ [Выбрать]
  1. void ExportToExcel(...) {
  2.         HRESULT hr = CoInitialize(NULL);
  3.         if (FAILED(hr))
  4.         {       return; }
  5.         Excel::_ApplicationPtr pXL;
  6.         if (FAILED(pXL.CreateInstance("Excel.Application")))
  7.         {       return; }
  8.         pXL->Workbooks->Add(Excel::xlWorksheet);
  9.         Excel::_WorksheetPtr pSheet = pXL->ActiveSheet;
  10.         Excel::RangePtr pRange = pSheet->Cells;
  11.         pRange->Item[1][1] = "ПК+";
  12. }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
На данный момент у меня реализовано следующим образом:
Должно быть точно также.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Да. Единственно что сохранение там (если не изменяет память) в формат xls, а не xlsx.
а мы и не сохраняем ничего :). Наша задача - вывод подготовленного к печати/редактированию/сохранению документа. т.е. на выходе получается открытый экселевский заполненный данными документ. А пользователь при желании может его сохранить в том формате, в котором захочет. На открывание экселевских файлов (мы ж не только в эксель пишем. иногда и из экселя данные получить нужно) это никак не влияет. открываются и xls и xlsx.
ну и пара примеров
1. запись (чисто для примера. ничего стоящего не пишется :) )
Код - C++ [Выбрать]
  1. void write()
  2. {
  3.         ::CoInitialize(NULL);
  4.         using namespace Excel;
  5.         _ApplicationPtr excel(_T("Excel.Application"));
  6.         // создаём новую книгу
  7.         _WorkbookPtr  book  = excel->Workbooks->Add();
  8.         _WorksheetPtr sheet = book->Worksheets->Item[1L];
  9.         //excel->Visible = true;
  10.         sheet->Range[_T("A1")]->Activate();
  11.         // Формируем заголвок
  12.         // статичные ячейки
  13.         sheet->Range[_T("A1:J2")]->HorizontalAlignment = -4108; // выровняли по центру по горизонтали
  14.         sheet->Range[_T("A1:J2")]->VerticalAlignment = -4108;// выровняли по центру по вертикали
  15.         sheet->Range[_T("A1:J2")]->WrapText = 1;        // разрешен перенос в ячейке
  16.         sheet->Range[_T("A1:J2")]->Font->Bold = true;   // весь текс выделен жирным
  17.  
  18.         Excel::RangePtr rng;
  19.         rng = sheet->Cells->Item[2L][1L];      
  20.         rng->RowHeight = 27.0f;
  21.  
  22.         rng = sheet->Cells->Item[1][1];
  23.         rng->ColumnWidth = 5.0f;
  24.         sheet->Range[_T("A1")]->FormulaR1C1 = _T("№№");
  25. //.....
  26.         ::CoUninitialize();
  27.         excel->Visible = true;
  28. }
  29.  

чтение (читается файл lpszFileName в вектор vecRawStr. в случае, если в ячейке была формула - прочитается РЕЗУЛЬТАТ вычислений а не сама формула)
Код - C++ [Выбрать]
  1. //...
  2. struct ExcelFileStr
  3. {
  4.         bool pluralChoice; // участвует ли запись в множественном выборе
  5.         bool IsCheck;  
  6.         std::vector<std::wstring> vecStr; // столбцы
  7. };
  8.  
  9. std::vector<ExcelFileStr> vecRawStr;    // вектор файла
  10. //...
  11. void read(LPTSTR lpszFileName)
  12. {
  13.         using namespace Excel;
  14.         _ApplicationPtr pApp(L"Excel.Application");
  15.         WorkbooksPtr pWorkBooks = pApp->GetWorkbooks();
  16.         _WorkbookPtr pWorkBook = pWorkBooks->Open(_bstr_t(lpszFileName), vtMissing, VARIANT_TRUE);
  17.         long i = 0, j = 0;
  18.  
  19.         try
  20.         {
  21.                 int nRows = 1, nCols = 1; // тут будут лежать реальные количества строк и столбцов
  22.  
  23.                 _WorksheetPtr pSheet = pWorkBook->Worksheets->GetItem(1);
  24.                 Excel::RangePtr pRange = pSheet->UsedRange;
  25.                 int startRow = 1, endRow = max(pRange->Rows->Count, nRows); nRows = endRow;
  26.                 int startCol = 1, endCol = max(pRange->Columns->Count, nCols); nCols = endCol;
  27.  
  28.                 vecRawStr.resize((size_t)(nRows));
  29.                 for (i = 0; i < nRows; i++)
  30.                 {
  31.                         vecRawStr[i].IsCheck = true;
  32.                         vecRawStr[i].pluralChoice = false;
  33.                         vecRawStr[i].vecStr.resize((size_t)(nCols));
  34.                 }
  35.  
  36.                 _variant_t varr = pRange->GetValue2(), val;
  37.                 long iLBound[2] = { 0,0 }, iUBound[2] = { 0,0 };
  38.                 HRESULT hr;
  39.                 _bstr_t str;
  40.                 if (FAILED(hr = SafeArrayGetLBound(varr.parray, 1, &iLBound[0]))) throw _com_error(hr);
  41.                 if (FAILED(hr = SafeArrayGetUBound(varr.parray, 1, &iUBound[0]))) throw _com_error(hr);
  42.                 if (FAILED(hr = SafeArrayGetLBound(varr.parray, 2, &iLBound[1]))) throw _com_error(hr);
  43.                 if (FAILED(hr = SafeArrayGetUBound(varr.parray, 2, &iUBound[1]))) throw _com_error(hr);
  44.                
  45.                 for (i = 0; i <= iUBound[0] - iLBound[0]; i++)
  46.                 {
  47.                         for (j = 0; j <= iUBound[1] - iLBound[1]; j++)
  48.                         {
  49.                                 long ind[2] = { iLBound[0] + i, iLBound[1] + j };
  50.                                 if (FAILED(hr = SafeArrayGetElement(varr.parray, ind, &val))) throw _com_error(hr);
  51.                                 try
  52.                                 {
  53.                                         vecRawStr[i].vecStr[j] = _bstr_t(val);
  54.                                 }
  55.                                 catch (_com_error &er)
  56.                                 { // Если поле имеет недопустимый формат
  57.                                         vecRawStr[i].vecStr[j] = _T("");
  58.                                 }
  59.                         }
  60.                 }
  61.         }
  62.         catch (_com_error &err)
  63.         {
  64.                 CString s; s.Format(L"Ошибка чтения файла <%s> Код: 0x%8X %s Строка=%d Столбец=%d", lpszFileName, err.Error(), err.ErrorMessage(), i, j);
  65.                 AfxMessageBox(s, MB_ICONERROR);
  66.                 vecRawStr.clear();
  67.         }
  68.         try
  69.         {
  70.                 pWorkBook->Close();
  71.                 pWorkBooks->Close();
  72.         }
  73.         catch (...) { ; }
  74. }
  75.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
На открывание экселевских файлов (мы ж не только в эксель пишем. иногда и из экселя данные получить нужно) это никак не влияет. открываются и xls и xlsx.
А вот тут ты похоже не прав. xlsx-формат появился в MS Office 2007. Так что xlsx-файл открыть из arx-файла, запущенного на PC с MS Office 2003 или более раннем не получится.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
А вот тут ты похоже не прав. xlsx-формат появился в MS Office 2007. Так что xlsx-файл открыть из arx-файла, запущенного на PC с MS Office 2003 или более раннем не получится.
снять видео? :):):) у меня стоит 2003 офис с паком для обработки наворотов 2007 офиса (это я про docx и xlsx). В компиляциях используется excel8.olb и замечательно читаются файлы xlsx. и да, на 97 офисе xlsx не откроется. но то уже не наши проблемы. главное один код для всех экселей. открытие файла обеспечевает непосредственно офис. если он сможет открыть - откроет

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
снять видео? :):):) у меня стоит 2003 офис с паком для обработки наворотов 2007 офиса (это я про docx и xlsx). В компиляциях используется excel8.olb и замечательно читаются файлы xlsx
Тут ключевые слова  "с паком для обработки наворотов 2007 офиса". Тогда проверь в MS Office 2000, для которого этого пака нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн ParavozzzАвтор темы

  • ADN OPEN
  • Сообщений: 20
  • Карма: 0
Николай Горлов, Александр Ривилис, БЛАГОДАРЮ ВАС! Пойду изучать :)

Оффлайн Николай Горлов

  • ADN
  • *
  • Сообщений: 238
  • Карма: 34
Тут ключевые слова  "с паком для обработки наворотов 2007 офиса". Тогда проверь в MS Office 2000, для которого этого пака нет.
ой, ффффсё, запутали меня окончательно :):):)
основной посыл был такой - если excel самостоятельно способен открыть экселевский файл (xls или xlsx), то программно это сделать можно, даже пользуясь excel8.olb
ну а если excel старенький и уже ни на что не годный, то тут два пути:
1. просить пересохранить в старом формате кого-то с более модным офисом
2. отказываться от старья и самому обзавестить этим самым модным офисом

короче говоря, минимально поддерживаемый офис зависит от выбранного olb файла. и не нужно городить огород под каждый офисный пакет отдельно, если взаимодействие с ним минимальное (на уровне прочитать три строки - записать два столбца)