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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Передача адреса как диапазона в экселе, какими средствами с++ лучше это сделать? 
:(
    Опции темы
Gunslinger
Дата 20.10.2008, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



Снова привет! И снова речь о MyCells smile 
Оказалось, что четыре координаты x1,y1,x2,y2 использовать не получится. Прочитать значение 2х объединенных ячеек в экселе возможно только через диапазон, и работает эта штука так:
Код


//<...>//OlePropertyGet("Range", "A1:B1");


Общий план:
Код

#ifndef MyCellsH
#define MyCellsH
#include <system.hpp>

struct Address {
                int x1;
                int y1;
               // int x2;
              //  int y2;
              //  Address(){};
              //  Address(int my_x1,int my_y1,int my_x2,int my_y2): x1(my_x1),y1(my_y1),x2(my_x2),y2(my_y2){};
               };
//------------------
class MyCells {
      private:
              Address addr;
              String Text;
       public:
              //---------------------- 
              bool IsTextValue(Variant& myCells)
                       {
                          AnsiString buff_text;
                          Variant buff_cell;
                          buff_cell=myCells.OlePropertyGet("Item", addr.x1,addr.y1);
                          buff_text=buff_cell.AsType(varString);
                          if(Text==buff_text) return true;
                          else false;
                         };
};
#endif

Сейчас проверяются ячейки только одинарные. А нужно еще объединенные по 2. Было бы здорово указывать напрямую, но в ОLE штука вроде 
Код

//<....>//OlePropertyGet("Item",addr.x1,addr.y1,addr.x2,addr.y2);

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

Мои варианты:
1. Хранить координаты ячейки как енум - для буквы соответствие цифра. 
2. Затем все соединять в строку.

Или может нах не париться и хранить адреса объектов MyCells как строки (они все равно используются только для сравнения), а перед передачей Оле - делать конкатенацию? Тогда нельзя будет делать парсинг по листу forом (тогда делать через енум или еще чего-нибудь в с++, о чем я не знаю).
PM MAIL   Вверх
J0ker
Дата 20.10.2008, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



excel можно переключить в режим адресации R1C1


--------------------
user posted image
PM MAIL   Вверх
Gunslinger
Дата 21.10.2008, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



Знаешь как? Нечто вроде 
Код

myExcel.OlePropertyGet("MoveAfterReturnDirection").OlePropertySet("ReferenceStyle","R1C1");

выдает ошибку.

Это сообщение отредактировал(а) Gunslinger - 21.10.2008, 09:57
PM MAIL   Вверх
xvr
Дата 21.10.2008, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Gunslinger @ 21.10.2008,  09:56)
Знаешь как? Нечто вроде 
Код

myExcel.OlePropertyGet("MoveAfterReturnDirection").OlePropertySet("ReferenceStyle","R1C1");

выдает ошибку.

Насколько я помню ничего переключать не надо, он и так воспримет адресацию в любом формате. Только R1C1 ничем не проще, чем A1, диапазон придется задавать все так же в виде 2х точек через ':' (R1C1:R2C2)
А что касается диапазона, то проще всего сделать класс для хранения координат (у тебя Address) и сделать ему метод, возвращающий этот адрес в виде строки
Код

class Address {
 int x1,y2,x2,y2;
public:
 
 String get_addr()
  {
    String rv;
    if (x1==x2 && y1==y2) rv.printf("%c%d",'A'+x1,y1);
    else rv.printf("%c%d:%c%d",'A'+x1,y1,'A'+x2,y2);
    return rv;
  }
};
Работает только до 26 столбца, если надо больше то нужно или делать формирование многобуквенных имен столбцов или переводить в формат R1C1


Это сообщение отредактировал(а) xvr - 21.10.2008, 10:15
PM MAIL   Вверх
Gunslinger
Дата 21.10.2008, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



xvr, а я сейчас отписывать в тему про OLE собралсяsmile
Уточненяюсь: R1C1 выглядит как, например, 12,1?


Это сообщение отредактировал(а) Gunslinger - 21.10.2008, 10:29
PM MAIL   Вверх
xvr
Дата 21.10.2008, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Gunslinger @ 21.10.2008,  10:28)
xvr, а я сейчас отписывать в тему про OLE собралсяsmile
Уточненяюсь: R1C1 выглядит как, например, 12,1?

Нет, оно выглядит как R12C1
PM MAIL   Вверх
Gunslinger
Дата 22.10.2008, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



Код

f=myWorkSheet.OlePropertyGet("Item",1).OlePropertyGet("Range","R9C9:R9C10").OlePropertyGet("value");

ошибка. С одним адресом - тоже. Точно режим переключать не нужно?

Добавлено @ 09:53
вижу 2 варианта:
1. Адресация А8:B8. Тогда нужно что-то думать о конвертации букв в цифры.
2. R1C8:R2C8. Нужно думать только о парсинге строки и выдерании цифр. При записи -  о конкатенации букв R,C,: с преобразованными в символы цифрами. Но тут проще, так как есть стандартный IntToStr. 

Это сообщение отредактировал(а) Gunslinger - 22.10.2008, 09:53
PM MAIL   Вверх
xvr
Дата 22.10.2008, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Gunslinger @ 22.10.2008,  09:48)
Код

f=myWorkSheet.OlePropertyGet("Item",1).OlePropertyGet("Range","R9C9:R9C10").OlePropertyGet("value");

ошибка. С одним адресом - тоже. Точно режим переключать не нужно?

Да, действительно нужно  smile Кроме того, еще надо учесть, что RC адресация относительная (смещения относительно текущей ячейки)  smile 

Цитата

Добавлено @ 09:53
вижу 2 варианта:
1. Адресация А8:B8. Тогда нужно что-то думать о конвертации букв в цифры.
Вещь достаточно тривиальная
Цитата

2. R1C8:R2C8. 
Не надо, гемороя с относительной адресацией будет больше

У Application есть метод ConvertFormula, может пригодится:
Цитата

Converts cell references in a formula between the A1 and R1C1 reference styles, between relative and absolute references, or both. Variant.

expression.ConvertFormula(Formula, FromReferenceStyle, ToReferenceStyle, ToAbsolute, RelativeTo)
expression    Required. An expression that returns one of the objects in the Applies To list.

Formula   Required Variant. A string that containis the formula you want to convert. This must be a valid formula, and it must begin with an equal sign.

FromReferenceStyle   Required XlReferenceStyle. The reference style of the formula.

XlReferenceStyle can be one of these XlReferenceStyle constants. 
xlA1 
xlR1C1 

ToReferenceStyle   Optional XlReferenceStyle. The reference style you want returned. If this argument is omitted, the reference style isn't changed; the formula stays in the style specified by FromReferenceStyle.

XlReferenceStyle can be one of these XlReferenceStyle constants. 
xlA1 
xlR1C1 

ToAbsolute   Optional XlReferenceStyle. Specifies the converted reference type. If this argument is omitted, the reference type isn't changed.

XlReferenceStyle can be one of these XlReferenceStyle constants. 
xlAbsolute 
xlAbsRowRelColumn 
xlRelRowAbsColumn

xlRelative
 

RelativeTo   Optional Variant. Optional Variant. A Range object that contains one cell. Relative references relate to this cell.

Example
This example converts a SUM formula that contains R1C1-style references to an equivalent formula that contains A1-style references, and then it displays the result.

inputFormula = "=SUM(R10C2:R15C2)"
MsgBox Application.ConvertFormula( _
    formula:=inputFormula, _
    fromReferenceStyle:=xlR1C1, _
    toReferenceStyle:=xlA1)

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


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



за ConvertFormula спасибо - запомню, если понадобится. К счастью не в этом проекте. И вообще не понадобится - запарил меня уже этот эксел, хочу уже программировать что-нибудь другое. Про засаду R1C1 тоже спасибо, а то я уже сравнение написал. 
Цитата(xvr @  22.10.2008,  14:12 Найти цитируемый пост)
Вещь достаточно тривиальная
 Для меня пока нет. Единственная мысль - enum. Но при этом  хочу оставить адресную структуру как есть, т.е. int x2, y2;. Можно ли присвоить номер enuma? Вроде:
Код

enum coord {A=1, B=2, C,D,E,F,H,...};
int x2=A;

?

PM MAIL   Вверх
J0ker
Дата 22.10.2008, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Gunslinger, скажите что вам нужно конкретно от экселя я вам пример сделаю пока время есть.


--------------------
user posted image
PM MAIL   Вверх
Gunslinger
Дата 22.10.2008, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



J0ker, спасибо за желание помочь, но с этим форумом я и так обленился. Смысл мысли такой: 
1. Oбъединенные ячейки можно читать только через Range. А там адрес в формате A1:B1. 
2. Есть класс MyCell, сварганенный общими силами. Это - контрольные ячеки, в которых хранится адрес и значение стопудово известных ячеек в экселе. Чтобы проверить, та структура файла, прежде чем читать, или нет.
3. Можно было бы хранить адреса в текстовом формате, как и Range, а сравнивать текст.
Но!
далее будет чтение записей. Сколько их будет - хз, так что чтение ячеей делать буду в for. Приростил x,y. Значит придется конвертировать int в string. C конвертером я сам разбирусь, вот только не уверен, можно ли хранить связку буква-цифра в enum (псевдокод в предыдущем посте) - с ним никогда не работал. Вот это меня интересует.
PM MAIL   Вверх
J0ker
Дата 22.10.2008, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



я не совсем понял что вы хотите делать с enum - enum это простая подстановка выполняемая на этапе компиляции
остальное чуть позже гляну
ковырялся я сто лет назад с экселем через COM может вспомню...

Добавлено через 2 минуты и 34 секунды
Цитата(Gunslinger @  22.10.2008,  21:14 Найти цитируемый пост)
1. Oбъединенные ячейки можно читать только через Range. А там адрес в формате A1:B1. 

если это конкретный документ или документ основанный на конкретном темплете - я применял именованные объекты - в экселе вы можете поименовать ячейки и рэнджи и потом обращаться к ним по имени


--------------------
user posted image
PM MAIL   Вверх
J0ker
Дата 23.10.2008, 02:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



вот сваял пример - visual studio - борланда нету... но принцип должен быть тем-же:

Код

#include "stdafx.h"
#include <iostream>
#include <objbase.h>

using namespace std;

#import "C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.DLL" \
    rename( "RGB", "MSORGB" ) \
    rename( "DocumentProperties", "MSODocumentProperties" )

using namespace Office;

#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"

using namespace VBIDE;

#import "C:\Program Files\Microsoft Office\OFFICE12\EXCEL.EXE" \
    include("IFont", "IPicture") \
    rename( "DialogBox", "ExcelDialogBox" ) \
    rename( "RGB", "ExcelRGB" ) \
    rename( "CopyFile", "ExcelCopyFile" ) \
    rename( "ReplaceText", "ExcelReplaceText" )


inline bool HR_FAILED(HRESULT &hr, HRESULT function) { return (hr = function) != S_OK; }

int _tmain(int argc, _TCHAR* argv[])
{

    HRESULT hr;

    if(HR_FAILED(hr, CoInitialize(NULL))) {
        cout << "CoInitialize error: " << hex << showbase << hr << endl;
        return hr;
    }

    Excel::_ApplicationPtr pApplication;
    if(HR_FAILED(hr, pApplication.GetActiveObject/*CreateInstance*/(_T("Excel.Application")))) {
        cout << "pApplication.CreateInstance error: " << hex << showbase << hr << endl;
        return hr;
    }


    try {
        int n = pApplication->Workbooks->Count;
        cout << "Workbooks count: " << n << endl;
        if(n) {
            Excel::_WorkbookPtr pBook = pApplication->ActiveWorkbook;
            int h = pBook->Sheets->Count;
            cout << "Sheets in active workbook: " << h << endl;
            if(h) {
                Excel::_WorksheetPtr pSheet = pBook->ActiveSheet;
                _bstr_t v = pSheet->Cells->Item[1][1];
                cout << "Cell \"A1\" in active sheet: " << v << endl;
            }
        }
    } catch (_com_error &err) {
        cout << "com error: " << err.Description() << " [" << err.Error() << "]" << endl;
    }

    return 0;
}


Добавлено @ 02:41
PS: я использовал import для упрощения решения, но в принципе можно и руками прописать все обращения к дисп-интерфейсу - но это геморно
я там вижу у вас на борланде тоже своя оболочка, так что должно быть похоже

Добавлено @ 02:44
PPS: да чуть не забыл - оно коннектится к запущеному приложению и читает ячейку A1 с активной страницы активной книги. Там где закоментаренное CreateInstance - можно создавать новый инстанс, соответственно он будет пустой - без книг.

Добавлено @ 02:49
PPPS:что-бы было понятно - такие вызовы как _bstr_t v = pSheet->Cells->Item[1][1]; - означают вызов pSheet->GetCells()->GetItem(...) с соответствующими параметрами - они просто в VC++ организованы через праперти - microsoft specific

PPPPS поправил немного


Это сообщение отредактировал(а) J0ker - 23.10.2008, 04:33


--------------------
user posted image
PM MAIL   Вверх
Gunslinger
Дата 23.10.2008, 08:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 842
Регистрация: 30.12.2006
Где: Астрахань

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



Цель кода только не понял. За раз все равно не даст обратиться сразу к двум ячейкам (по крайней мере, через Cells, а с Range опять приходим к вопросу конвертации буква-цифра и наоборот).
Цитата(J0ker @  22.10.2008,  22:41 Найти цитируемый пост)
если это конкретный документ или документ основанный на конкретном темплете
 вот этого не знаю, знаю только, что документов будет много и из разных источников, хотя расположение таблицы стандартное.  

Цитата(J0ker @  22.10.2008,  22:41 Найти цитируемый пост)
я не совсем понял что вы хотите делать с enum - enum это простая подстановка выполняемая на этапе компиляции
. это я не знаю, как привязать букву к цифре, чтоб букву адреса эксель ячейки можно было конвертнуть в цифру и присвоить адресу объкта MyCells. Другой вариант - символьный массив. по цифре в координате адреса (например, int x=10) читаем из массива соответствующий символ.

з.ы. По вашему коду вопрос. В борланде ничего подобного вроде ActiveWorkbook, ActiveSheet не делал... Хотя через Оле работал, там через проперти брал сразу "Workbooks", "Cells" и т.д. За меня борлан делает такую подстановку или это способ обращения другой?

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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Gunslinger @ 22.10.2008,  14:47)
Единственная мысль - enum. Но при этом  хочу оставить адресную структуру как есть, т.е. int x2, y2;. Можно ли присвоить номер enuma? Вроде:
Код

enum coord {A=1, B=2, C,D,E,F,H,...};
int x2=A;

?

Присвоить можно, а преобразовать в строку - нет (получится обычное число)

Вот функция, преобразующая номер в букву (или несколько)
(Писал прямо тут, не проверял)

Код

String int2col(int idx)
{
 String rv;
 if (idx<=0) return "?";
 --idx;
 if (idx<26) rv.printf("%c",'A'+idx); else
 if ((idx-=26)<676) rv.printf("%c%c",'A'+idx/26,'A'+idx%26);
 else {idx-=676; rv.printf("%c%c%c",'A'+idx/676,'A'+(idx%676)/26,'A'+idx%26);
 return rv;
}


Добавлено через 5 минут и 49 секунд
Цитата(Gunslinger @ 23.10.2008,  08:23)
з.ы. По вашему коду вопрос. В борланде ничего подобного вроде ActiveWorkbook, ActiveSheet не делал... Хотя через Оле работал, там через проперти брал сразу "Workbooks", "Cells" и т.д. За меня борлан делает такую подстановку или это способ обращения другой?

В Borland'е надо брать компонент ExcelApplication с вкладки Office2K (или OfficeXP, смотря какой набор контролов активирован), там будет сразу все в виде нормальных пропертей и методов

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0619 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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