Продолжаем цикл статей по работе с API САПР КОМПАС-3D Сергея Норсеева, кандидата технических наук, инженера-программиста АО «ВНИИ «Сигнал», автора книги «Разработка приложений под КОМПАС в Delphi». В качестве среды используется C++ Builder. Продолжаем разговор об основной надписи. В двух предыдущих статьях (ознакомиться с ними можно здесь и здесь) мы подробно рассмотрели различные способы записи в основную надпись. Здесь же поговорим о ее чтении.
Для чтения содержимого ячеек основной надписи предназначен метод ksGetStampColumnText интерфейса ksStamp. Ниже приводится его прототип.
Глядя на этот прототип, возникает ложное ощущение, что у метода один входной параметр, но это не так. Параметр numb является возвращаемым значением. В нем метод возвращает номер просмотренной с его помощью ячейки. За один вызов он позволяет просматривать только одну ячейку.
Содержимое просмотренной ячейки возвращается методом в виде динамического массива (ksDynamicArray) типа TEXT_LINE_ARR. То есть его элементами являются интерфейсы ksTextLineParam (динамические массивы и интерфейс ksTextLineParam рассматривались на прошлом уроке).
Существует два способа задания номера требуемой ячейки. Первый – с помощью метода ksColumnNumber интерфейса ksStamp. Второй – посредством многократного вызова метода ksGetStampColumnText.
После каждого вызова метод ksGetStampColumnText переходит к «следующей» непустой ячейке. Все непустые ячейки упорядочены в порядке их заполнения. В этом порядке метод ksGetStampColumnText их и перечисляет. В случае, если метод достиг конца своего внутреннего буфера непустых ячеек, он возвращает NULL.
Согласно документации КОМПАС параметр numb может быть равен NULL. Однако, как показывают мои эксперименты, в этом случае метод ksGetStampColumnText также возвращает NULL.
Использовать метод ksGetStampColumnText нужно в режиме редактирования основной надписи, то есть после вызова метода ksOpenStamp() и до вызова ksCloseStamp().
Ниже приводится исходный текст программы, демонстрирующей чтение содержимого одной ячейки основной надписи.
Данный пример открывает документ, читает ячейку основной надписи с фамилией автора документа и выводит на экран строку с ее содержимым.
Помимо работы с основной надписью в данном примере демонстрируется перечисление элементов массива ksDynamicArray. Наличие вложенного цикла объясняется структурой массива, возвращаемого методом ksGetStampColumnText. Она приводилась в одной из прошлых статей нашего цикла.
Для упрощения примера мы не обрабатываем спецсимволы, а также не проверяем типы получаемых массивов.
Обратите внимание: значение параметра, передаваемого в метод ksGetStampColumnText, равно нулю и отличается от номера ячейки, содержимое которой мы получаем. Номер требуемой ячейки определяется методом ksColumnNumber.
Вызов метода ksGetStampColumnText меняет значение переменной numb. Она становится равной ksStAuthor, то есть номеру ячейки, содержимое которой мы читали. Если повторно вызвать метод ksGetStampColumnText, он прочитает содержимое «следующей» ячейки и запишет её номер в переданную ему переменную.
Для пустой ячейки метод ksGetStampColumnText возвращает пустую строку.
Изменим предыдущий пример так, чтобы он читал содержимое всех непустых ячеек основной надписи.
Пример основной надписи чертежа
В данном примере перечисляются все непустые ячейки основной надписи. Их содержимое записывается в текстовый файл «Stamp_Content.txt» (программа создает его в каталоге приложения). Каждой ячейке соответствует строка вида
<Номер ячейки>: <Содержимое ячейки>
Обратите внимание: мы не используем метод ksColumnNumber. Ячейки перечисляются методом ksGetStampColumnText. Как говорилось ранее, он перечисляет ячейки в порядке их заполнения. Так на моем тестовом примере содержимое файла Stamp_Content.txt оказалось следующим.
В файл попадают только заполненные ячейки, так как метод ksGetStampColumnText не возвращает содержимое пустых ячеек.
Учтите, что метод ksGetStampColumnText перечисляет ячейки только в прямом направлении. Если с помощью метода ksColumnNumber мы переместим его на ячейку номер 2, а потом начнем вызывать его в цикле, то он перечислит ячейки с номерами 2, 1, 110, 3 и 9 (для моего примера), а ячейки с номерами 6, 32 и 8 перечислены не будут.
При достижении конца ячеек метод ksGetStampColumnText возвращает значение NULL.
В данной статье мы рассмотрели вопрос чтения содержимого ячеек основной надписи. Для выполнения этой операции приходится работать с массивом интерфейсов ksTextLineParam. Он имеет достаточно сложное строение, поэтому самая сложная часть программ – это его корректный анализ. Тем не менее, если запомнить структуру, приведенную в предыдущей статье цикла, то работа с ним не вызовет никаких сложностей.
Продолжение следует, следите за новостями блога.
Сергей Норсеев, к.т.н., автор книги «Разработка приложений под КОМПАС в Delphi».
Содержание цикла уроков «Работа с API КОМПАС-3D»
Метод ksGetStampColumnText
Для чтения содержимого ячеек основной надписи предназначен метод ksGetStampColumnText интерфейса ksStamp. Ниже приводится его прототип.
LPDISPATCH ksGetStampColumnText (
long* numb //Номер ячейки
);
Глядя на этот прототип, возникает ложное ощущение, что у метода один входной параметр, но это не так. Параметр numb является возвращаемым значением. В нем метод возвращает номер просмотренной с его помощью ячейки. За один вызов он позволяет просматривать только одну ячейку.
Содержимое просмотренной ячейки возвращается методом в виде динамического массива (ksDynamicArray) типа TEXT_LINE_ARR. То есть его элементами являются интерфейсы ksTextLineParam (динамические массивы и интерфейс ksTextLineParam рассматривались на прошлом уроке).
Существует два способа задания номера требуемой ячейки. Первый – с помощью метода ksColumnNumber интерфейса ksStamp. Второй – посредством многократного вызова метода ksGetStampColumnText.
После каждого вызова метод ksGetStampColumnText переходит к «следующей» непустой ячейке. Все непустые ячейки упорядочены в порядке их заполнения. В этом порядке метод ksGetStampColumnText их и перечисляет. В случае, если метод достиг конца своего внутреннего буфера непустых ячеек, он возвращает NULL.
Согласно документации КОМПАС параметр numb может быть равен NULL. Однако, как показывают мои эксперименты, в этом случае метод ksGetStampColumnText также возвращает NULL.
Использовать метод ksGetStampColumnText нужно в режиме редактирования основной надписи, то есть после вызова метода ksOpenStamp() и до вызова ksCloseStamp().
Пример. Чтение одной ячейки
Ниже приводится исходный текст программы, демонстрирующей чтение содержимого одной ячейки основной надписи.
//Подключаемся к КОМПАС
KompasObjectPtr kompas;
kompas.CreateInstance(L"KOMPAS.Application.5");
//Формируем полный путь к документу с читаемой основной надписью
WideString str;
str = ExtractFileDir(Application->ExeName) + L"\\Документ.cdw";
//Открываем документ
Document2DPtr Document2D;
Document2D = (Document2DPtr)kompas->Document2D();
Document2D->ksOpenDocument(SysAllocString(str.c_bstr()), false);
//Получаем интерфейсы строки и компоненты
TextItemParamPtr TextItemParam;
TextItemParam = (TextItemParamPtr)kompas->GetParamStruct(ko_TextItemParam);
TextLineParamPtr TextLineParam;
TextLineParam = (TextLineParamPtr)kompas->GetParamStruct(ko_TextLineParam);
//Получаем интерфейс основной надписи
StampPtr Stamp;
Stamp = (StampPtr)Document2D->GetStamp();
//Открываем режим редактирования основной надписи
Stamp->ksOpenStamp();
//Читаем содержимое ячейки
Stamp->ksColumnNumber(ksStAuthor);
long numb = 0;
ksDynamicArrayPtr DynamicArrayLines;
DynamicArrayLines = (ksDynamicArrayPtr)Stamp->ksGetStampColumnText(&numb);
//Анализируем полученный массив
str = WideString(L"");
if(DynamicArrayLines)
{
//Перечисляем интерфейсы ksTextLineParam
for(int iline = 0; iline < DynamicArrayLines->ksGetArrayCount(); ++iline)
{
//Читаем элемент массива
DynamicArrayLines->ksGetArrayItem(iline, TextLineParam);
ksDynamicArrayPtr DynamicArrayItems;
DynamicArrayItems = (ksDynamicArrayPtr)TextLineParam->GetTextItemArr();
if(!DynamicArrayItems)
continue;
//Перечисляем интерфейсы ksTextItemParam
for(int iitem = 0; iitem < DynamicArrayItems; ++iitem)
{
DynamicArrayItems->ksGetArrayItem(iitem, TextItemParam);
str += WideString(TextItemParam->get_s());
}
//Удаляем массив интерфейсов ksTextItemParam
DynamicArrayItems->ksDeleteArray();
DynamicArrayItems.Unbind();
}//for(int iline = 0; iline < DynamicArray->ksGetArrayCount(); ++iline)
//Удаляем массив интерфейсов ksTextLineParam
DynamicArrayLines->ksDeleteArray();
DynamicArrayLines.Unbind();
}//if(DynamicArrayLines)
//Закрываем режим редактирования основной надписи
Stamp->ksCloseStamp();
//Освобождаем ресурсы
Stamp.Unbind();
TextItemParam.Unbind();
TextLineParam.Unbind();
Document2D.Unbind();
kompas->set_Visible(true);
kompas.Unbind();
//Выводим извлеченную строку
ShowMessage(str);
Данный пример открывает документ, читает ячейку основной надписи с фамилией автора документа и выводит на экран строку с ее содержимым.
Помимо работы с основной надписью в данном примере демонстрируется перечисление элементов массива ksDynamicArray. Наличие вложенного цикла объясняется структурой массива, возвращаемого методом ksGetStampColumnText. Она приводилась в одной из прошлых статей нашего цикла.
Для упрощения примера мы не обрабатываем спецсимволы, а также не проверяем типы получаемых массивов.
Обратите внимание: значение параметра, передаваемого в метод ksGetStampColumnText, равно нулю и отличается от номера ячейки, содержимое которой мы получаем. Номер требуемой ячейки определяется методом ksColumnNumber.
Вызов метода ksGetStampColumnText меняет значение переменной numb. Она становится равной ksStAuthor, то есть номеру ячейки, содержимое которой мы читали. Если повторно вызвать метод ksGetStampColumnText, он прочитает содержимое «следующей» ячейки и запишет её номер в переданную ему переменную.
Для пустой ячейки метод ksGetStampColumnText возвращает пустую строку.
Пример. Чтение всех ячеек
Изменим предыдущий пример так, чтобы он читал содержимое всех непустых ячеек основной надписи.
Пример основной надписи чертежа
//Подключаемся к КОМПАС
KompasObjectPtr kompas;
kompas.CreateInstance(L"KOMPAS.Application.5");
//Формируем полный путь к документу с читаемой основной надписью
WideString str;
str = ExtractFileDir(Application->ExeName) + L"\\Документ.cdw";
//Подготавливаем файл, в который будем писать основную надпись
HANDLE hOutFile;
hOutFile = CreateFile("Stamp_Content.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
//Открываем документ
Document2DPtr Document2D;
Document2D = (Document2DPtr)kompas->Document2D();
Document2D->ksOpenDocument(SysAllocString(str.c_bstr()), false);
//Получаем интерфейсы строки и компоненты
TextItemParamPtr TextItemParam;
TextItemParam = (TextItemParamPtr)kompas->GetParamStruct(ko_TextItemParam);
TextLineParamPtr TextLineParam;
TextLineParam = (TextLineParamPtr)kompas->GetParamStruct(ko_TextLineParam);
//Получаем интерфейс основной надписи
StampPtr Stamp;
Stamp = (StampPtr)Document2D->GetStamp();
//Открываем режим редактирования основной надписи
Stamp->ksOpenStamp();
//Читаем содержимое ячейки
long numb = 0;
ksDynamicArrayPtr DynamicArrayLines;
DynamicArrayLines = (ksDynamicArrayPtr)Stamp->ksGetStampColumnText(&numb);
//Анализируем полученный массив
while(DynamicArrayLines)
{
str = WideString(IntToStr(numb)) + WideString(L" : ");
//Перечисляем интерфейсы ksTextLineParam
for(int iline = 0; iline < DynamicArrayLines->ksGetArrayCount(); ++iline)
{
//Читаем элемент массива
DynamicArrayLines->ksGetArrayItem(iline, TextLineParam);
ksDynamicArrayPtr DynamicArrayItems;
DynamicArrayItems = (ksDynamicArrayPtr)TextLineParam->GetTextItemArr();
if(!DynamicArrayItems)
continue;
//Перечисляем интерфейсы ksTextItemParam
for(int iitem = 0; iitem < DynamicArrayItems; ++iitem)
{
DynamicArrayItems->ksGetArrayItem(iitem, TextItemParam);
str += WideString(TextItemParam->get_s());
}
//Удаляем массив интерфейсов ksTextItemParam
DynamicArrayItems->ksDeleteArray();
DynamicArrayItems.Unbind();
}//for(int iline = 0; iline < DynamicArray->ksGetArrayCount(); ++iline)
//Записываем строку в файл
str += WideString(L"\r\n");
DWORD r;
WriteFile(hOutFile, str.c_bstr(), str.Length() * sizeof(wchar_t), &r, NULL);
//Удаляем массив интерфейсов ksTextLineParam
DynamicArrayLines->ksDeleteArray();
//Переходим к следующей ячейке
DynamicArrayLines=(ksDynamicArrayPtr)Stamp->ksGetStampColumnText(&numb);
}//while(DynamicArrayLines)
//Закрываем режим редактирования основной надписи
Stamp->ksCloseStamp();
//Освобождаем ресурсы
Stamp.Unbind();
TextItemParam.Unbind();
TextLineParam.Unbind();
Document2D.Unbind();
kompas->set_Visible(true);
kompas.Unbind();
//Закрываем файл с содержимым основной надписи
CloseHandle(hOutFile);
В данном примере перечисляются все непустые ячейки основной надписи. Их содержимое записывается в текстовый файл «Stamp_Content.txt» (программа создает его в каталоге приложения). Каждой ячейке соответствует строка вида
<Номер ячейки>: <Содержимое ячейки>
Обратите внимание: мы не используем метод ksColumnNumber. Ячейки перечисляются методом ksGetStampColumnText. Как говорилось ранее, он перечисляет ячейки в порядке их заполнения. Так на моем тестовом примере содержимое файла Stamp_Content.txt оказалось следующим.
6 : 1:1
32 : A4
8 : 1
2 : Обозначение
1 : Деталь
110 : Норсеев
3 : Материал
9 : Организация
В файл попадают только заполненные ячейки, так как метод ksGetStampColumnText не возвращает содержимое пустых ячеек.
Учтите, что метод ksGetStampColumnText перечисляет ячейки только в прямом направлении. Если с помощью метода ksColumnNumber мы переместим его на ячейку номер 2, а потом начнем вызывать его в цикле, то он перечислит ячейки с номерами 2, 1, 110, 3 и 9 (для моего примера), а ячейки с номерами 6, 32 и 8 перечислены не будут.
При достижении конца ячеек метод ksGetStampColumnText возвращает значение NULL.
Заключение
В данной статье мы рассмотрели вопрос чтения содержимого ячеек основной надписи. Для выполнения этой операции приходится работать с массивом интерфейсов ksTextLineParam. Он имеет достаточно сложное строение, поэтому самая сложная часть программ – это его корректный анализ. Тем не менее, если запомнить структуру, приведенную в предыдущей статье цикла, то работа с ним не вызовет никаких сложностей.
Продолжение следует, следите за новостями блога.
Сергей Норсеев, к.т.н., автор книги «Разработка приложений под КОМПАС в Delphi».