На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Работа с Excel из C++ Builder'a
    Задача вроде бы не сложная: вывести в TImage график из Excel. Для этого запускаю Excel через OLE и открываю в нем нужный мне файл с графиками:

    ExpandedWrap disabled
      Variant vVarApp, vVarBook, vVarBooks, vVarSheet, vVarSheets, charts;
      vVarApp   = CreateOleObject("Excel.Application");
      vVarApp.OlePropertySet("Visible",true);
      vVarBooks = vVarApp.OlePropertyGet("Workbooks");
      vVarBooks.OleProcedure("Open","C:\\test.xls");

    Далее начинается самое интересное. Непонятно, как обратиться к нужному мне листу по его имени? Например, лист называется ДМ, как его сделать активным? Как я понял, есть код для переключения между листами по индексу:
    ExpandedWrap disabled
      vVarBook   = vVarBooks.OlePropertyGet("Item",1);
      vVarSheets = vVarBook.OlePropertyGet("Worksheets");
      vVarSheet  = vVarSheets.OlePropertyGet("Item",2);
      vVarSheet.OleProcedure("Activate");

    Этим кодом я перешел на Лист 2. Но дело в том, что у меня в документе листы идут так:
    Диаграмма1 | Лист 1 | Лист 2 | Лист 3
    Так вот Лист 1, 2 и 3 мне удалось сделать активными, а как выбрать лист "Диаграмма1" вобще не понятно.
      vVarSheets.OlePropertyGet("Item","Диаграмма1"); не работает?
      или vVarBook.OlePropertyGet("Worksheets","Диаграмма1");
        Цитата trainer @
        vVarSheets.OlePropertyGet("Item","Диаграмма1"); не работает?
        или vVarBook.OlePropertyGet("Worksheets","Диаграмма1");

        Пробовал. Не работает. Текст ошибки:
        "Project raised exception class EOleSysError with message 'Неизвестное имя'" или 'Ошибка' в 1м варианте.
          попробуй так :
          ExpandedWrap disabled
            Variant vVarCharts = vVarApp.OlePropertyGet("Charts"); // либо vVarBook - поэксперементируешь
            Variant vChart = vVarCharts .OlePropertyGet("Item",1);
            popsa, отлично. Прогресс есть. Эксель открывается, копируется график и закрывается. Осталось решить два вопроса:
            1. Как все-таки копировать график с определенного листа, зная его имя, а не по индексу. Вот так копируется первый график:
            ExpandedWrap disabled
              vVarCharts = vVarApp.OlePropertyGet("Charts");
              vChart = vVarCharts.OlePropertyGet("Item",1);
              vChartArea = vChart.OlePropertyGet("ChartArea");
              vChartArea.OleProcedure("Copy");

            Нашел один способ - перебирать все листы в цикле, пока не найдется нужный с именем. Но тут есть одна проблема - индексация листов и графиков может не совпадать, т.к. все идет по порядку и на 1м листе графика может небыть. Вот код перебора листов:

            ExpandedWrap disabled
              Variant vSheetName;
              short nSheetIndex = 0;
              while (vSheetName != edSheet->Text)
              {
                  nSheetIndex++;
                  vVarSheets = vVarApp.OlePropertyGet("Sheets");
                  vVarSheet = vVarSheets.OlePropertyGet("Item",nSheetIndex);
                  vSheetName = vVarSheet.OlePropertyGet("Name");
              }
               
               
              vVarCharts = vVarApp.OlePropertyGet("Charts");
              vChart = vVarCharts.OlePropertyGet("Item",nSheetIndex);
              vChartArea = vChart.OlePropertyGet("ChartArea");
              vChartArea.OleProcedure("Copy");


            2. Столкнулся с одной помехой автоматизации. Т.к. весь процесс должен проходить невидимо для пользователя без вопросов и предупреждений, свойства Visible и DisplayAlerts выставляются в false. Но заметил такую закономерность: на простом документе без связей все отрабатывает нормально, но в документе, который имеет связи с другими документами при открытии задается вопрос (игнорируя DisplayAlerts), обновить ли связи. После закрытия этого диалога сразу же выдается ошибка "Runtime error '13': Type mismatch", которая ломает весь процесс автоматизации. Нашел, что Номер ошибки 13 означает "Недопустимые данные". А вот что именно недопустимое и как ее избежать?

            Добавлено
            Первый вопрос решил. Вот как:

            ExpandedWrap disabled
              Variant vSheetName;
              short nSheetIndex = 0;
              while (vSheetName != edSheet->Text)
              {
                  nSheetIndex++;
                  vVarSheets = vVarApp.OlePropertyGet("Sheets");
                  vVarSheet = vVarSheets.OlePropertyGet("Item",nSheetIndex);
                  vSheetName = vVarSheet.OlePropertyGet("Name");
              }
               
               
              vVarSheet.OleProcedure("Select");
              vChartArea = vVarSheet.OlePropertyGet("ChartArea");
              vChartArea.OleProcedure("Copy");


            Остается вопрос с ошибкой 13 (Run-time error). Интересно, что если открывать этот файл вручную, отвечая на вопрос об обновлении связей, то ошибка не появляется. Значит дело не в файле, а в скрипте.
              ;) читал описание здесь ?
              судя по
              ExpandedWrap disabled
                vVarSheet=vVarBook.OlePropertyGet("Worksheets","Желтый лист");

              тоже самое можно сделать и с диаграммой. По второму вопросу ничего сказать не могу :(
                Цитата Shad0FF @
                в документе, который имеет связи с другими документами при открытии задается вопрос (игнорируя DisplayAlerts), обновить ли связи.
                Для того, чтоб он не задавался - есть свойство AskToUpdateLinks (там же, в Application). Сбрось его в False...
                  Цитата Shad0FF @
                  Но заметил такую закономерность: на простом документе без связей все отрабатывает нормально, но в документе, который имеет связи с другими документами при открытии задается вопрос (игнорируя DisplayAlerts), обновить ли связи.
                  Параметр UpdateLinks функции Open коллекции Workbooks установи в VARIANT_FALSE
                    popsa, по идее должно быть вот так правильно:
                    ExpandedWrap disabled
                      Variant  vVarApp,vVarBooks,vVarBook,vVarSheets,vVarSheet,vVarCells,vVarCell,vChartArea;
                      vVarApp = CreateOleObject("Excel.Application");
                      vVarApp.OlePropertySet("Visible",true);
                      vVarBooks = vVarApp.OlePropertyGet("Workbooks");
                      vVarBooks.OleProcedure("Open",edFile->Text.c_str());
                       
                       
                      vVarBook = vVarBooks.OlePropertyGet("Item",1);
                      vVarSheet = vVarBook.OlePropertyGet("Worksheets","Диаграмма1");
                      vVarSheet.OleProcedure("Activate");
                       
                      vChartArea = vVarSheet.OlePropertyGet("ChartArea");

                    Но на последней строчке выдает ошибку "Неизвестное имя".



                    trainer
                    volvo877
                    Установил, но все равно при открытии Ошибка 13 (run-time error) и еще после нее ошибка 1004 "Method 'cells' of object '_Global' failed. Может ли это быть из-за того, что у меня эксель 2003й (2007го под рукой нету чтоб проверить, вечером смогу посмотреть).
                      Вчера проверял на 2007м офисе. На той машине все файлы есть, поэтому при открытии документа эксель не требует обновлять связи. Но ошибки все равно появляются. Как 13я так и 1004я. Начал эксперементировать. Вот весь код, который копирует график в буффер обмена и вставляет в моей проге в TImage:

                      ExpandedWrap disabled
                        Variant vVarApp, vVarBook, vVarBooks, vVarSheet, vVarSheets, vVarCharts, vChart, vChartArea;
                         
                        vVarApp = CreateOleObject("Excel.Application");
                        vVarApp.OlePropertySet("Visible",false);
                        vVarApp.OlePropertySet("DisplayAlerts",false);
                        vVarApp.OlePropertySet("AskToUpdateLinks",false);
                        vVarBooks = vVarApp.OlePropertyGet("Workbooks");
                        vVarBooks.OleProcedure("Open",edFile->Text.c_str());
                         
                         
                        Variant vSheetName;
                        short nSheetIndex = 0;
                        while (vSheetName != edSheet->Text)
                        {
                            nSheetIndex++;
                            vVarSheets = vVarApp.OlePropertyGet("Sheets");
                            vVarSheet = vVarSheets.OlePropertyGet("Item",nSheetIndex);
                            vSheetName = vVarSheet.OlePropertyGet("Name");
                        }
                         
                         
                        vVarSheet.OleProcedure("Select");
                        vChartArea = vVarSheet.OlePropertyGet("ChartArea");
                        vChartArea.OleProcedure("Copy");
                         
                         
                        Clipboard()->Open();
                        unsigned int ClipboardHandle = Clipboard()->GetAsHandle(CF_METAFILEPICT);
                        if (ClipboardHandle != 0)
                        imgGraph->Picture->LoadFromClipboardFormat(CF_METAFILEPICT, ClipboardHandle, 0);
                        Clipboard()->Close();
                         
                         
                        vVarApp.OlePropertyGet("WorkBooks",1).OleProcedure("Close");
                        vVarApp.OleProcedure("Quit");
                        vVarSheets.Clear();
                        vVarApp.Clear();


                      Как выяснилось, если из кода убрать последние 4 строки, которые закрывают эксель, то все работает на УРА - ошибок нету, график копируется и отображается в TImage, только вот эксель остается висеть в памяти, но ошибок никаких не возникает. Я так понял, что все дело в том участке кода, где происходит открытие листа с графиком и копирование графика, т.к. код закрытия экселя написан правильно и врядле дело в нем.


                      P.S. popsa, мне так и не получилось обращаться к листу по имени (код в предыдущем сообщении). При выполнении получаю ошибку.
                        Цитата
                        P.S. popsa, мне так и не получилось обращаться к листу по имени (код в предыдущем сообщении). При выполнении получаю ошибку.

                        я думал, что это будет выглядеть так
                        ExpandedWrap disabled
                          vVarSheet = vVarBook.OlePropertyGet("Charts","Диаграмма1");


                        ;) не получиться, ковыряй дальше
                          Цитата Shad0FF @
                          Вчера проверял на 2007м офисе. На той машине все файлы есть, поэтому при открытии документа эксель не требует обновлять связи. Но ошибки все равно появляются. Как 13я так и 1004я.
                          Только что проверил у себя на 2002/2003 Офисе (сделал файл, который берет Source Data для чарта из другого XLS-файла) - никаких ошибок не возникает, все открывается, без предупреждений, без ошибок, копирует картинку и заталкивает ее в TImage, закрывается... Не знаю уж что у тебя там за файлы, что они дают сбой...

                          Кстати, цикл я бы переделал на постусловие:

                          ExpandedWrap disabled
                                String vSheetName;
                                short nSheetIndex = 0;
                                vVarSheets = XL.OlePropertyGet("Sheets"); // На кой ты это делаешь на каждой итерации?
                                do
                                {
                                    nSheetIndex++;
                                    vVarSheet = vVarSheets.OlePropertyGet("Item",nSheetIndex);
                                    vSheetName = vVarSheet.OlePropertyGet("Name");
                                }
                                while(vSheetName != edSheet->Text);
                            Макросы в файле или в загрузке случаем не присутствуют?
                              Всем огромнейшее спасибо!!! При использовании кода, кототорый предложил popsa ошибок не возникает. Но еще нужно протестировать работоспособность кода, т.к. заметил что раз было эксель не закрылся, а продолжал висеть в памяти.

                              volvo877, все-таки вариант с прямым обращением к графику более удобный. Кстате, да, выполнять vVarSheets = XL.OlePropertyGet("Sheets"); на каждой итерации не нужно и не правильно.

                              trainer, макросы в файле присутствуют. Это может как-то влиять?
                                Цитата Shad0FF @
                                макросы в файле присутствуют. Это может как-то влиять?
                                Естественно. Особенно если выполнять макросы от более поздней версии на более ранней.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0420 ]   [ 16 queries used ]   [ Generated: 2.05.24, 14:00 GMT ]