Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C++ и Excel, Cells? 
:(
    Опции темы
BucheRRR73
  Дата 11.11.2006, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



В общем, мне необходимо экспортировать в книгу Excel большой объем данных.

По всем правилам открываю excel:

using namespace Excel;

CLSID clsid;
CLSIDFromProgID(L"Excel.Application", &clsid);

_ApplicationPtr pApp;
pApp.CreateInstance (clsid,NULL);
pApp ->PutVisible (0,VARIANT_TRUE);

_WorkbookPtr   pBook  = pApp->GetWorkbooks()->Add();
_WorksheetPtr  pSheet = pBook->Worksheets->GetItem(_variant_t((long)1));

Все ок, можно занести данные в ячейку так:

pSheet->Range["B1"]->Value2 = "Произвольный текст";

но имя ячейки указывается в текстовом формате - "B1", с этим в цикле много данных не положишь!
А мне необходимо получить ячейку например через:

pSheet->Cells[2,1]->Value2 = "Произвольный текст";

чтобы можно было заносить данные например из массива mass через цикл...

for(i = 1; i<10; i++)
   for(j = 1; j<10; j++)
      pSheet->Cells[i,j]->Value2 = mass[i,j];

НО! Cells[i,j] просто НЕ работает!!! Как надо с ним работать, как правильно обращаться?
PM MAIL   Вверх
Partizan
Дата 11.11.2006, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 4
Всего: 67



Где пишешь? Если в C++B то может есть резон поюзать OLE Automation и тип TVariant?


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
BucheRRR73
Дата 11.11.2006, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



Да, пишу в Си, а можно поподробнее о "OLE Automation и тип TVariant?"

PM MAIL   Вверх
Partizan
Дата 11.11.2006, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 4
Всего: 67



Я о среде разработки говорю, а не о языке... если пишешь в Borland C++ Builder, то там есть такой волшебный тип, который называется TVariant....с его помощью в ехселе можно много чего сотворить...в том числе обратиться к ячейке...

з.ы.Я тут сча перечитал твоё сообщение... Чтото синтаксис обращения к ячейке двумерного массива у тебя неверный....


Попробуй так...
Код

for(i = 1; i<10; i++)
   for(j = 1; j<10; j++)
      pSheet->Cells[i][j]->Value2 = mass[i][j];





--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
BucheRRR73
Дата 11.11.2006, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



Это-то я знаю, что в борланде такой тип есть, а я пишу в Visual studio 6 (((
Такие дела, а там, насколько я знаю есть не волшебный тип VARIANT, который чудес не делает...

На счет двумерного массива, просто как пример привел, не обращай внимание, суть жзе понятна)).

Ну так что, не подскажешь, как можно еще занести двумерный массив в таблицу?
Очень нужно.. Ну как-то же люди заносят...  smile 

PM MAIL   Вверх
Partizan
Дата 11.11.2006, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 4
Всего: 67



так как более рациональными методами в данном вопросе не располагаю... предлагаю тупое решение "прямо в лоб"

формировать строку типа "А1" , "A2" .... и т.д. просто увеличением в цикле аски кода на 1....суть ясна?


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
BucheRRR73
Дата 11.11.2006, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



 smile 
Тут та все ясно!
Лень матушка...  smile 
Неохота!))
Лано, пойду тогда тупо работать со строками...))
Если у кого есть какие идеи по этому поводу, прошу, высказывайтесь не стесняйтесь...
PM MAIL   Вверх
archimed7592
Дата 11.11.2006, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



тип variant не просто так называется. он может содержать в себе любой тип данных. в т. ч. массив. и один волшебным вызовом ф-ции ты можешь заполнить любой прямоугольник в таблице. в интерфейсе Range есть волшебное поле Value2. в него и нужно засунуть variant array. скорость просто несравнимая smile

зы. для формул аналогичное поле Formula


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
BucheRRR73
Дата 11.11.2006, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



Цитата(archimed7592 @ 11.11.2006,  15:39)
тип variant не просто так называется. он может содержать в себе любой тип данных. в т. ч. массив. и один волшебным вызовом ф-ции ты можешь заполнить любой прямоугольник в таблице. в интерфейсе Range есть волшебное поле Value2. в него и нужно засунуть variant array. скорость просто несравнимая smile

зы. для формул аналогичное поле Formula

нука,нука, можно поподробнее...
Конкретный простейший пример.
Допустим нам надо заполнить ячейки данных "A3:B5" массивом 2*3 mass.

Мы должны сначала присвоить переменной типа VARIANT (var) переменнную mass, а потом
сделать pSheet->Range["B1", var];
Я просто не понял как внести значения данной переменной типа VARIANT.

PM MAIL   Вверх
archimed7592
Дата 11.11.2006, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



ниже результаты моих попыток осознать automation на с++. что-то взято из msdn, что-то из древних познаний аж из самого delphi 6...короче говоря, чем смогу тем, помогу:
Код
#include <windows.h>

#pragma comment(lib, "oleaut32.lib")

#include "oleauto.h"

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    SAFEARRAY *psa; // сам массив.
    SAFEARRAYBOUND rgsabound [2]; // границы

    // устанавливаем границы
    rgsabound [0].lLbound = 0; 
    rgsabound [0].cElements = 5;

    rgsabound [1].lLbound = 0;
    rgsabound [1].cElements = 3;

    // создаем массив
    psa = SafeArrayCreate (VT_VARIANT, 1, rgsabound);

    // блокируем массив
    SafeArrayLock (psa);
    
    for (int i = 0; i < rgsabound [0].cElements; ++i)
        for (int j = 0; j < rgsabound [1].cElements; ++j)
        {
            long rgIndices [2] = {i, j}; // индексы элемента
            
            VARIANT *pvData; // указатель на элемент

            SafeArrayPtrOfIndex (psa, rgIndices, (void **) &pvData); // получаем указатель

            VariantInit (pvData); // инициализируем элемент
            
            if (rand () > RAND_MAX / 2) // как звезды сложатся :)
            {
                pvData->vt = VT_I4; // тип варианта Int32
                V_I4 (pvData) = rand (); // устанавливаем значение
            }
            else
            {
                OLECHAR str [100]; // строка
                wsprintf (str, L"%d ! str ! %d", rand (), rand ()); // генерим строку
                pvData->vt = VT_BSTR; // тип варианта - строка
                V_BSTR (pvData) = SysAllocString (str); // создаем строку и устанавливаем значение
            };
        };

    SafeArrayUnlock (psa); // разблокируем массив

    VARIANT varArray; // вариант-массив
    VariantInit (&varArray); // инициализируем
    varArray.vt = VT_ARRAY; // тип = массив
    V_ARRAY (&varArray) = psa; // устанавливаем значение

    pSheet->Range["A1:С5"]->Value2 = varArray; // заливаем в таблицу

    /* далее идет поэлементное удаление строк.
     * я хз нужно это делать или нет, но лучше перестраховаться ;)
     */
    SafeArrayLock (psa);
    
    for (int i = 0; i < rgsabound [0].cElements; ++i)
        for (int j = 0; j < rgsabound [1].cElements; ++j)
        {
            long rgIndices [2] = {i, j};
            VARIANT *pvData;
            SafeArrayPtrOfIndex (psa, rgIndices, (void **) &pvData);
            if (pvData->vt == VT_BSTR)
            {
                SysFreeString (V_BSTR (pvData)); 
                pvData->vt = VT_EMPTY;
            }
        };

    SafeArrayUnlock (psa);

    // удаляем сам массив
    SafeArrayDestroy (psa);

    return 0;
}

кстати, что такое BSTR - я не знаю...предполагаю, что какие-то специальные строки, но не факт...короче говоря может быть можно просто V_BSTR (pvData) = str, а может и низя - эт не ко мне. насчет удаления этих строк тож. не знаю удаляет ли safearray свои элементы, пологаясь на их тип...

зы. вот нормальный, рабочий вариант на c#. в нем все почти также, как здесь smile, только немного проще. что же касается работоспособности этого варианта - vc6 у меня нету. прикрутить excel к vc8 win32 con app мне не удалось, но удалось прикрутить oleaut32 чего в принципе достаточно для вариантов. короче говоря тестируй, а там увидим...

Это сообщение отредактировал(а) archimed7592 - 11.11.2006, 22:32


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
BucheRRR73
Дата 11.11.2006, 23:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



Цитата(archimed7592 @  11.11.2006,  22:31 Найти цитируемый пост)
ниже результаты моих попыток осознать automation на с++. что-то взято из msdn, что-то из древних познаний аж из самого delphi 6...короче говоря, чем смогу тем, помогу:


RESPECT!!! Спасибо огромное тебе, сейчас попробую... Буду разбираться...
PM MAIL   Вверх
BucheRRR73
  Дата 11.11.2006, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 35
Регистрация: 23.10.2006

Репутация: нет
Всего: нет



Мдяяя, сделал вроде все как сказали (archimed7592), а что-то не работает... Не заносит он туды значения...

Надо что-то с Cells придумать, не зря же данное поле есть в переменной листа книги...
 smile 

Вот пока мои результаты...

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  poka.zip 1,94 Kb
PM MAIL   Вверх
CLIPSA
Дата 12.11.2006, 02:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 126
Регистрация: 6.10.2006

Репутация: нет
Всего: 2



Почитай здесь 
http://forum.vingrad.ru/topic-36410.html
PM MAIL   Вверх
Partizan
Дата 12.11.2006, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 4
Всего: 67



да там всё тоже без числовых индексов....


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
archimed7592
Дата 12.11.2006, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



таки удалось прикрутить мне excel к vc8, спасибо CLIPSA, натолкнула на использование #import, правда долго парился над clsid'ами - у меня к сожалению нету ms office 2000, а в 2003 таких файлов нет smile
Код
#include "stdafx.h"

#include <windows.h>

#include <stdlib.h>
#include <stdio.h>

#include "objbase.h"
#include "oleauto.h"
#include "comutil.h"
#include "Office.h"

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize (NULL);
    CLSID clsid;
    CLSIDFromProgID (L"Excel.Application", &clsid);

    Excel::_ApplicationPtr pApp;
    pApp.CreateInstance (clsid,NULL);
    pApp->Visible [0] = VARIANT_TRUE;


    Excel::_WorkbookPtr pBook  = pApp->Workbooks->Add ();
    Excel::_WorksheetPtr pSheet = pBook->Worksheets->Item [(long) 1];

    SAFEARRAY *psa; // сам массив.
    SAFEARRAYBOUND rgsabound [2]; // границы

    // устанавливаем границы
    rgsabound [0].lLbound = 0; 
    rgsabound [0].cElements = 5;

    rgsabound [1].lLbound = 0;
    rgsabound [1].cElements = 7;

    // создаем массив
    psa = SafeArrayCreate (VT_VARIANT, 2, rgsabound); // здесь была ошибка - забыл указать 2 (двух мерный массив)

    // блокируем массив
    SafeArrayLock (psa);
    
    for (int i = 0; i < rgsabound [0].cElements; ++i)
        for (int j = 0; j < rgsabound [1].cElements; ++j)
        {
            long rgIndices [2] = {i, j}; // индексы элемента
            
            VARIANT *pvData; // указатель на элемент

            SafeArrayPtrOfIndex (psa, rgIndices, (void **) &pvData); // получаем указатель

            // VariantInit не нужно - SafeArrayCreate автоматом инициализирует массив
            // VariantInit (pvData); // инициализируем элемент
            
            // раз есть такой прекрасный класс, то почему бы им не пользоваться?
            _variant_t vData;

            if (rand () > RAND_MAX / 2) // как звезды сложатся :)
            {
                //pvData->vt = VT_I4; // тип варианта Int32
                //V_I4 (pvData) = rand (); // устанавливаем значение
                vData = (long) rand (); // все проще, чем я предполагал
            }
            else
            {
                OLECHAR str [100]; // строка
                wsprintf (str, L"%d ! str ! %d", rand (), rand ()); // генерим строку
                //pvData->vt = VT_BSTR; // тип варианта - строка
                //V_BSTR (pvData) = SysAllocString (str); // создаем строку и устанавливаем значение
                vData = str;
            };
            *pvData = (VARIANT) vData; // копируем получившийся VARIANT
            vData.Detach (); // делаем detach. обязательно, иначе умный класс уничтожит соззанную в нем же строку.
        };

    SafeArrayUnlock (psa); // разблокируем массив

    VARIANT varArray; // вариант-массив
    VariantInit (&varArray); // инициализируем
    varArray.vt = VT_ARRAY | VT_VARIANT; // тип = массив // здесь тоже была ошибка - нужно было указывать, что массив из VARIANT'ов
    V_ARRAY (&varArray) = psa; // устанавливаем значение
    

    // ну и вот заветный кусочек: запихивание большого диапазона в таблицу
    _variant_t COMvarArray; // создаем специальную c++ обертку для VARIANT
    COMvarArray.Attach (varArray); // прикручиваем VARAINT-массив к обертке

    pSheet->Range["A1"]["G5"]->Value2 = COMvarArray; // заливаем в таблицу обертку
    COMvarArray.Detach (); // откручиваем массив от обертки

    /* далее идет поэлементное удаление строк.
     * я хз нужно это делать или нет, но лучше перестраховаться ;)
     */
    // этот кусок насколько я понял не нужен
    /* SafeArrayLock (psa);
    
    for (int i = 0; i < rgsabound [0].cElements; ++i)
        for (int j = 0; j < rgsabound [1].cElements; ++j)
        {
            long rgIndices [2] = {i, j};
            VARIANT *pvData;
            SafeArrayPtrOfIndex (psa, rgIndices, (void **) &pvData);
            if (pvData->vt == VT_BSTR)
            {
                SysFreeString (V_BSTR (pvData)); 
                pvData->vt = VT_EMPTY;
            }
        };

    SafeArrayUnlock (psa);*/

    // удаляем сам массив - он сам сообразит, что нужно освободить все строки
    SafeArrayDestroy (psa);

    pBook->Close (VARIANT_FALSE);
    pApp->Quit ();

    CoUninitialize ();

    return 0;
}


Добавлено @ 15:12 
зы. сейчас посмотрел poka.zip, там office.h:
Код
#import "C:\Program Files\Common Files\Microsoft Shared\Office10\MSO.DLL" 
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.olb" 
#import "C:\Program Files\Microsoft Office\Office10\MSWORD.olb" rename("ExitWindows","ExitWindowsEx")
#import "C:\Program Files\Microsoft Office\Office10\excel.exe" rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") \
         rename("DocumentProperties", "DocumentPropertiesXL") exclude("IFont","IPicture")

а у меня (libid честно выдирал из соседнего проекта на c#) 
Код
#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" version("2.3") lcid("0") \
    rename ("RGB", "_RGB") \
    rename ("DocumentProperties", "_DocumentProperties")

#import "libid:0002E157-0000-0000-C000-000000000046" version("5.3") lcid("0")

#import "libid:00020813-0000-0000-C000-000000000046" version("1.5") lcid("0") \
    rename ("RGB", "_RGB") \
    rename ("DialogBox", "_DialogBox") \
    rename ("CopyFile", "_CopyFile") \
    rename ("ReplaceText", "_ReplaceText")
сомневаюсь, что когда-либо буду работать с COM на с++, но тем не менее меня интересует вопрос: как правильней? через libid или прямо на excel.exe? имеется ввиду ранее связывание.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0600 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.