Добрый день!
Kompas V14 SP1, RAD Studio XE4
Мне немного непонятна логика работы по вставке строки вертикального текста в таблицу на чертеже. Когда произвожу вставку вертикального текста в ячейку, то помимо вставки происходит ещё добавление символа переноса строки (\n) уже не в вертикальный текст, а в обычную строку. Каким образом можно убрать этот перенос?
Делаю так:
IDrawingTablePtr pDrawTable;
ITablePtr pTable;
ITableRangePtr pTableRange;
ITableCellPtr pCell;
ITextPtr pCellText;
ITextLinePtr pTextLine;
ISymbols2DContainerPtr pSym2DContainer;
IViewPtr pActiveView;
IApplicationPtr pKompas7;
IViewsPtr pViews;
IKompasDocument2DPtr pDoc2D;
IViewsAndLayersManagerPtr pViewsAndLayersManager;
//Подготовка
pKompas7 = (IDispatch*)CreateKompasApplication();
pDoc2D = pKompas7->ActiveDocument;
pViewsAndLayersManager = pDoc2D->ViewsAndLayersManager;
pViews = pViewsAndLayersManager->Views;
pActiveView = pViews->ActiveView;
pSym2DContainer = pActiveView;
//Создание таблицы
pSym2DContainer->DrawingTables->Add(2, 2, 50, 10, ksTableTileLayoutEnum::ksTTLNotCreate, &pDrawTable);
pDrawTable->X = 0;
pDrawTable->Y = 0;
pTable = pDrawTable;
//Получение ячейки
pCell = pTable->get_Cell(1, 1);
pCellText = pCell->Text;
//Ввод вертикального текста
pTextLine = pCellText->AddTextLine(ksTextLineType::ksTLVerticalText, StringToOleStr(UnicodeString(L"Текст")));
pDrawTable->_Update();
Как вариант, можно попробовать сначала очистить от того, что было IText::Clear, но не факт, что поможет.
Да и почему AddTextLine, а не просто Add?
Попробовал pCellText->Clear() - не помогает.
Только с помощью AddTextLine и AddTextLineBefore можно добавить вертикальный текст, или я не прав?
До этого такой код проходил великолепно на KompasV11, а в V14 появилась эта проблема.
Нет, не правы IText::Add, возвращаемое значение: - указатель на интерфейс ITextLine строка текста.
ITextLine::TextLineType, может быть равно ksTLVerticalText - вертикальный текст.
ITextLine::TextLineType доступно только для чтения, компилятор только что подтвердил
Да действительно только, для чтения.
Получилось только так удалить.
Попробовал по вашему методу
//Ввод вертикального текста
pTextLine = pCellText->AddTextLine(ksTextLineType::ksTLVerticalText, StringToOleStr(UnicodeString(L"Текст")));
pTextLine = pCellText->AddTextLine(ksTextLineType::ksTLVerticalText, StringToOleStr(UnicodeString(L"")));
pDrawTable->_Update();
pTextLine = pCellText->get_TextLine(1);
if (pTextLine)
{
if (!(pTextLine->Delete())) ShowMessage("Delete() = False");
pDrawTable->_Update();
} else ShowMessage("pTextLine = NULL");
В итоге Delete() выдаёт false на любой строке.
А у вас на скриншоте в центральной ячейке перед 12345 стоит \n ?
Но у нас и языки разные, как раз не стоит, но мусор остался, от #10+#13.
А в вашем примере вы избавились от \n? Потому как на скриншоте видно что стоит \n после 12345
Ещё раз повторяю, остаётся мусор, пробовал по разному, через вариантные массивы, просто символами форматирования, но сама AddTextLine уже делает форматирование и вставку, а управляющие символы не попадают в массивы, строки и тем более подстроки.
Я так понимаю что это баг. Как то можно уведомить разработчиков компаса чтобы откорректировали это в sp2?
Это не баг, а стандарты форматирования, просто Компас не относится к текстовым редакторам.
Ладно, если это не баг, то как сделать чтобы вертикальный текст в ячейке был ровно по средине а не сомещением?
ITextLine - установить нужные параметры форматирования.
//Ввод вертикального текста
pTextLine = pCellText->AddTextLine(ksTextLineType::ksTLVerticalText, StringToOleStr(UnicodeString(L"Текст")));
pTextLine->Align = ksAlignEnum::ksAlignCenter;
Такой метод не помог. Есть ли ещё способы как можно реализоват выравнивание по средине вертикального текста?
Можно не по центру выравнивать, а по какой либо стороне и за счёт отступов выравнивать.
Благодарю за советы!
Но я считаю это не доработкой, когда текст можно выровнить только если добавить строку перед вставкой вертикального текста (что помогло в моём случае, но не поможет если ячейку сжать повертикали). Перенос строки должен появлятся только после добавления второй и последующих строк.
Добрый день! Подскажите пожалуйста как на Delphi при использовании API7 организовать чтение обычного горизонтального текста в ячейках существующей таблицы, задавая номер столбца и строки.
Набросал такой код процедуры, но он не работает (ошибка на закомментированной строке):
procedure ReadTable();//Чтение таблицы
var
pDrawTable: IDrawingTable;
pDrawTables: IDrawingTables;
pTable: ITable;
pTableRange: ITableRange;
pCell: ITableCell;
pCellText: IText;
pTextLine: ITextLine;
I,J:integer;
SM: string;
begin
SM:='';
pKompasDocument2D := ksDoc as iKompasDocument2D;
pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
pViews := pViewsAndLayersManager.Views;
for J := 0 to pViews.Count-1 do
begin
pView := pViews.ViewByNumber[J];
pView.Current := true;
pDrawingContainer := pView as iDrawingContainer;
pSymbols2DContainer := pView as iSymbols2DContainer;
pDrawTables:= pSymbols2DContainer.DrawingTables;
pDrawTable:= pDrawTables.Item[0] as IDrawingTable;
pTable:= pDrawTable as ITable;
pCell:= pTable.Cell[1,1];
//pCellText:= pCell.Text;
SM:= SM + pCellText.Str + ' ';
end;
end;
Надеюсь на помощь знатоков Delphi и API7. Может я вовсе все неправильно делаю?
Внимательней читайте справку, на рисунке выше показано правильно.
http://forum.ascon.ru/index.php/topic,24881.msg180085.html#msg180085
Спасибо, Sabahs !!!!
Вот какой код у меня получился - он рабочий:
procedure ReadTable();//Чтение таблицы
var
pDrawTable: IDrawingTable;
pDrawTables: IDrawingTables;
pTable: ITable;
pTableRange: ITableRange;
pCell: ITableCell;
pCellText: IText;
pTextLine: ITextLine;
I,J, RW,CL:integer;
begin
SM:='';
pKompasDocument2D := ksDoc as iKompasDocument2D;
pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
pViews := pViewsAndLayersManager.Views;
for I := 0 to pViews.Count-1 do
begin
pView := pViews.ViewByNumber;
pView.Current := true;
pDrawingContainer := pView as iDrawingContainer;
pSymbols2DContainer := pView as iSymbols2DContainer;
pDrawTables:= pSymbols2DContainer.DrawingTables;
pDrawTable:= pDrawTables.Item[0] as IDrawingTable;
pTable:= pDrawTable as ITable;
if pTable<>nil then
begin
for RW := 0 to pTable.RowsCount-1 do
begin
for CL := 0 to pTable.ColumnsCount-1 do
begin
pCell:= pTable.Cell[RW,CL];
if pCell<>nil then
begin
pCellText:=pCell.Text as IText;
if pCellText<>nil then
begin
SM:= SM + pCellText.Str + ' ';
end;
end;
end;
SM:=SM+#13+#10;
end;
end;
end;
pDrawTable:=nil;
pDrawTables:=nil;
end;
Только еще хотелось бы перебирать не все таблицы подряд (хотя в моем коде задана таблица с индексом 0), а по указанию или выделенную таблицу считывать. Как это сделать? Даже не представляю.
ISelectionManager.SelectedObjects - Получить массив выделенных объектов в виде SAFEARRAY | VT_DISPATCH, если выделена одна таблица, то функция вернёт интерфейс IDispatch таблицы, то запись будет верна:
Air:=pSelectionManager.SelectedObjects;
pDrawTable:=Air as IDrawingTable;, но если выделенный элемент не таблица или их несколько, то при такой записи будет вылет.
Sabahs, премного Вам благодарен. Еще маленький вопросик: как организовать удаление столбца/строки? И как быть если при этом есть пересекающие строки/столбцы - разбивать их, удалять или при удалении столбца/строки не вручную, а через API7 они мешать не будут?
Удалять программно не удалял, поэтому экспериментируйте, сделайте удаление в ручную, а затем повторите программно удовлетворивший Вас алгоритм.
Цитата: Sabahs от 17.04.14, 22:21:03
ISelectionManager.SelectedObjects - Получить массив выделенных объектов в виде SAFEARRAY | VT_DISPATCH, если выделена одна таблица, то функция вернёт интерфейс IDispatch таблицы, то запись будет верна:
Air:=pSelectionManager.SelectedObjects;
pDrawTable:=Air as IDrawingTable;, но если выделенный элемент не таблица или их несколько, то при такой записи будет вылет.
Можно наверно и без массивов обойтись. Например при переборе объектов, который уже есть в коде проверять свойство:
ISelectionManager::IsSelected
Синтаксис Automation:
BOOL IsSelected( LPDISPATCH Object );
Я прав?
Зачем перебирать, когда можно сразу получить указатель на таблицу, ненужно бояться массивов, как огня.
Не то что я боюсь массиво как огня. Просто не до конца разобрался с их использованием. Вы давали ссылку вот сюда: http://forum.ascon.ru/index.php/topic,24894.msg180294.html#msg180294 Тут лишь часть кода.
Неясно например как декларируется в разделе VAR имя массива Air.
Air:OleVariant;
У меня Delphi не узнает константу VT_DISPATCH. Где она задается или хотя бы чему она равна? В приведенном здесь: http://forum.ascon.ru/index.php/topic,24894.msg180294.html#msg180294 примере есть VT_DISPATCH и массив Air. У меня в аналогичном Step3_API7_3D ничего такого не находится. странно (((
В начале этой темы затрагивалось добавление вертикального текста в таблицу. А как считать вертикальный текст? Приведенная процедура в этом случае выдает символ @ вместо текста, содержащегося в вертикальной строке в ячейке таблицы.
Цитата: Sprinter500 от 18.04.14, 17:32:11
У меня Delphi не узнает константу VT_DISPATCH. Где она задается или хотя бы чему она равна? В приведенном здесь: http://forum.ascon.ru/index.php/topic,24894.msg180294.html#msg180294 примере есть VT_DISPATCH и массив Air. У меня в аналогичном Step3_API7_3D ничего такого не находится. странно (((
С этой проблемой разобрался - надо было в Uses модуля добавить ActiveX.
Однако после компиляции в процессе работы возникает ошибка в строке:
Air:=pSelectionManager.SelectedObjects;
Что не так?
var
...
pKompasDocument2D1 : IKompasDocument2D1;
pSelectionManager : ISelectionManager;
Air:OleVariant;
....
begin
...
pSelectionManager := pKompasDocument2D1.SelectionManager;
Air:=pSelectionManager.SelectedObjects;
....
Вот так объявлял все. И почему то вылетает на Air:=pSelectionManager.SelectedObjects;
Забыл объявить:
pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
Теперь ошибка на этой строке - почему то pKompasDocument2D1 остается nil
Как Вы получили pKompasDocument2D?
unit WKMPS;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
ksTLB,ksConstTLB,ComObj,
ks2DCOM_TLB,ks3DCOM_TLB,LDefin2D,LDefin3D,ksAPI7,ksAuto, ActiveX;
var
Document2D: ksDocument2D;
DocumentParam: ksDocumentParam;
KOMPAS :IApplicationDisp;
ksDocs :IDocumentsDisp;
ksDoc :IKompasDocumentDisp;
//ksDoc2D1 :IKompasDocument2D1Disp;
pKompasDocument2D : IKompasDocument2D;
//pKompasDocument2D1 : IKompasDocument2D1;
pViewsAndLayersManager : IViewsAndLayersManager;
pViews : IViews;
pView : IView;
pSymbols2DContainer : ISymbols2DContainer;
pDrawingContainer : IDrawingContainer;
pLeaders : ILeaders;
pLeader : ILeader;
pPositionLeader : IPositionLeader;
pDrawingTexts : IDrawingTexts;
pDrawingText : IDrawingText;
pDrawingObject : IDrawingObject;
pText : IText;
pSelectionManager : ISelectionManager;
SM: widestring;
SourceStr: widestring;
procedure OpenDOC(Fname: string);//Открыть документ
procedure ReadTable();//Чтение таблицы
function InitCMPS(): bool;//Активация КОМПАСа
implementation
function InitCMPS(): bool;//Активация КОМПАСа
begin
try
KOMPAS:=GetActiveOleObject('KOMPAS.Application.7') as IApplicationDisp;
ksDocs:=IDocumentsDisp(KOMPAS.ActiveDocument);
ksDoc:=IKompasDocumentDisp(ksDocs);
//ksDoc2D1:= IKompasDocument2D1Disp(ksDocs);
result:=true;
except
KOMPAS:=CreateOleObject('KOMPAS.Application.7') as IApplicationDisp;
KOMPAS.Visible:=TRUE;
result:=false;
end;
end;
procedure OpenDOC(Fname: string);//Открыть документ
begin
TRY
ksDocs:=IDocumentsDisp(KOMPAS.Documents);
ksDoc:=IKompasDocumentDisp(ksDocs.Open(Fname, TRUE, FALSE));
EXCEPT
ksDocs:=nil;
ksDoc:=nil;
END;
end;
procedure ReadTable();//Чтение таблицы
var
pDrawTable: IDrawingTable;
pDrawTables: IDrawingTables;
pTable: ITable;
pTableRange: ITableRange;
pCell: ITableCell;
pCellText: IText;
pTextLine: ITextLine;
//Air:OleVariant;
I,J, RW,CL:integer;
begin
SM:='';
pKompasDocument2D := ksDoc as iKompasDocument2D;
//pKompasDocument2D1 := ksDoc2D1 as iKompasDocument2D1;
pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
//if pKompasDocument2D1<>nil then pSelectionManager := pKompasDocument2D1.SelectionManager;
//pSelectionManager := pKompasDocument2D1.SelectionManager;
pViews := pViewsAndLayersManager.Views;
for I := 0 to pViews.Count-1 do
begin
pView := pViews.ViewByNumber;
pView.Current := true;
pDrawingContainer := pView as iDrawingContainer;
pSymbols2DContainer := pView as iSymbols2DContainer;
pDrawTables:= pSymbols2DContainer.DrawingTables;
//Air:=pSelectionManager.SelectedObjects;
//if ( VarType(Air)=(VT_ARRAY Or VT_DISPATCH) ) then
//begin
// end;
for J := 0 to pDrawTables.Count-1 do
begin
pDrawTable:= pDrawTables.Item[J] as IDrawingTable;
//if pSelectionManager.IsSelected(pDrawTable)=true then
// begin
pTable:= pDrawTable as ITable;
if pTable<>nil then
begin
for RW := 0 to pTable.RowsCount-1 do
begin
for CL := 0 to pTable.ColumnsCount-1 do
begin
pCell:= pTable.Cell[RW,CL];
if pCell<>nil then
begin
pCellText:=pCell.Text as IText;
if pCellText<>nil then
begin
if pCellText.Str='' then SM:= SM + 'пуст' + ' '
else SM:= SM + pCellText.Str + ' ';
end;
end;
end;
SM:=SM+#13+#10;
end;
end;
//end;
end;
end;
pDrawTable:=nil;
pDrawTables:=nil;
end;
end.
var
ksDoc :IKompasDocument;
pKompasDocument2D : IKompasDocument2D;
pKompasDocument2D1 : IKompasDocument2D1;
ksDoc:=KOMPAS.ActiveDocument;
pKompasDocument2D := ksDoc as iKompasDocument2D;
pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
Тут без проверок, если документ не 2D, то вылет.
Сделал все как было предписано, и все равно вылетает на:
pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
Прилагаю весь проект, может станет яснее что не так. Пока хотел в процедуре procedure ReadTable(); сделать эту функцию, а RENM() пока не трогал, хотя некоторые элементы туда тоже внес. Все что вызывает ошибки закомментировано.
http://yadi.sk/d/wpD8fY59MmEck
По ссылки ролик, пользуйтесь отладчиком, у меня работает, единственное пришлось вручную загрузить документ.
Чтобы не грузить документ вручную, загружаете программно (см. рис.).
В общем все подключение мне придется переделывать чтобы заработало. С тем как удалять строки и столбцы я разобрался - ничего сложного. Правда жаль что програмно они как и вручную при наличии пересекающих их объединенных ячеек - не удаляются. Таким образом остался один не решенный вопрос:
Как считать вертикальный текст в таблице? В начале этой темы говорится лишь про запись вертикального текста.
А чем вертикальный текст отличается от горизонтального?
ITextLine.TextLineType
Я так считывал:
pCell:= pTable.Cell[RW,CL];
if pCell<>nil then
begin
pCellText:=pCell.Text as IText;
if pCellText<>nil then
begin
if pCellText.Str='' then SM:= SM + 'пуст' + ' '
else SM:= SM + pCellText.Str + ' ';
end;
end;
Хотя делал и через TextLine. В обоих случаях текст считывался, но только горизонтальный. Вертикальный в обоих случаях давал символ '@'.
Цитата: Sabahs от 19.04.14, 12:26:05
http://yadi.sk/d/wpD8fY59MmEck
По ссылки ролик, пользуйтесь отладчиком, у меня работает, единственное пришлось вручную загрузить документ.
Чтобы не грузить документ вручную, загружаете программно (см. рис.).
У тебя в этом примере Компас создается с нуля и открывается документ, а как аналогично для уже открытого документа организовать подключение?
Ошибка тут: pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
При создавании оболочки Компаса с нуля и открытия ошибки не возникает
ksDoc:=KOMPAS.ActiveDocument;
и т.д.
Ну у меня так и есть:
ksDoc:=KOMPAS.ActiveDocument;
Я переделал так чтобы имена были как в скриншоте. Сначала попытка заполучить активный документ, если его нет то в другой процедуре создается Компас и открывается файл :
function InitCMPS(): bool;//Активация КОМПАСа
begin
try
KompasApi:=GetActiveOleObject('KOMPAS.Application.7') as IApplication;
pDocuments := KompasApi.Documents;
ksDoc := KompasApi.ActiveDocument;
//pDocuments:=KompasApi.Documents;
//ksDoc:=KompasApi.ActiveDocument;
pKompasDocument2D := ksDoc as iKompasDocument2D;
//pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
result:=true;
except
KompasApi:=CreateOleObject('KOMPAS.Application.7') as IApplication;
KompasApi.Visible:=TRUE;
result:=false;
end;
end;
procedure OpenDOC(Fname: string);//Открыть документ
begin
TRY
pDocuments:=KompasApi.Documents;
ksDoc:=pDocuments.Open(Fname, TRUE, FALSE);
pKompasDocument2D := ksDoc as iKompasDocument2D;
pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
EXCEPT
pDocuments:=nil;
ksDoc:=nil;
END;
end;
И еще это компилятору не нравится: pDrawTable:=Air as IDrawingTable;
Цитата: Sprinter500 от 19.04.14, 15:27:25
У тебя в этом примере Компас создается с нуля и открывается документ, а как аналогично для уже открытого документа организовать подключение?
Ошибка тут: pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;
При создавании оболочки Компаса с нуля и открытия ошибки не возникает
У меня ошибки нет.
Так у меня все тоже самое. Странно. Как такое может быть? Можешь прислать твой проект? Я посмотрю будет ошибка или нет.
Так весь проект на картинке.
Не совсем. Видишь - ползунок есть, что сверху и снизу еще не видно. Может что то в uses есть что у меня не забито.
Я тебе в ICQ подал запрос на авторизацию. Можешь подтвердить? - так удобнее и быстрее будет общаться.
Я в долгу не останусь - как доделаю прогу тебе вышлю, занятная будет и пригодится, если конечно ты не чисто программируешь, а еще и чертишь в КОМПАСе.
Я чисто программирую и в ICQ не сижу, она у меня не установлена, а то, что в uses, здесь http://forum.ascon.ru/index.php/topic,24096.msg191014.html#msg191014 можно посмотреть.
Ну а в виде архива RAR или ZIP трудно выложить свой проект? он же пустой, нет ничего секретного. Просто я хочу понять в чем загвоздка при кажущейся идентичности кода.
Может у меня версия API от 13-го, а у тебя более новая корректно работает?
Мне кажется настолько хорошо в API компаса разбираетесь только Вы, и спросить больше не у кого. Единственное что быстрого диалога не получается, как при голубиной почте )))
Смотрите.
Ничего не менял в твоем проекте. Запустил - нажал кнопку и на тебе - такая же ошибка
У тебя еще точка останова стояла... Видать дело или в Delphi или в устраненном глюке более новой версии API, которая у тебя.
Отложим пока эти выделения. Подскажи лучше пож-та как все таки читать вертикальный текст, я как ни крутил все символ @ выскакивает.
Сегодня работать, грех.
Работа и творчество не могут быть и ни когда не были грехом. Грех - это безделье, праздновремяпровождение, но не работа и творчество. Не знаю какой враг христианства выдумал эту сентенцию про грех работы в христианские праздники. И в конце концов - работа работе рознь.
Тогда и поможете, товарищу у меня всё равно кода готового нет.
Сегодня понедельник не грех и поработать :)
Ну что продолжим?
1. В чем может быть причина нежелания подключения pKompasDocument2D1 := pKompasDocument2D as iKompasDocument2D1;, если на одном и том же коде у кого-то работает, а у кого-то нет?
2. Почему компилятору не нравится выражение: pDrawTable:=Air as IDrawingTable; ?
3. Как правильно считывать вертикальный текст из таблицы, чтобы не выводился символ "@" ?
ЦитироватьКак правильно считывать вертикальный текст из таблицы
Использовать свойство интерфейса строки текста ITextLine.TextLineData - интерфейс дополнительных данных строки.
Ух-ты как сложно! Я бы в жизнь не догадался. Вынесу этот участок в отдельную процедуру. Спасибо большое!!! Буду пробовать. Если без проблем заработает, то останется только разобраться проблему подключения IKompasDocument2D1 и с вытаскиванием таблицы из массива SAFEARRAY
Sabahs, если не трудно, пожалуста выложи полный текст процедуры - чтобы все объявление посмотреть и чем заканчивается.
Текст.
Организвал так:
...
if pCellText.Str<>'@' then MATR[RW-RW1,CL-CL1]:= pCellText.Str
else MATR[RW-RW1,CL-CL1]:= READVERTICAL(pCellText); //Вызов процедуры в случае нечитаемости текста
...
//Сама процедура:
function READVERTICAL(pText : IText): widestring;
var
I,J,K : integer;
S : Widestring;
pText1 : IText;
pTextLine1:ITextLine;
pTextItem:ITextItem;
begin
I:=pText.Count;
Dec(I);
S:='';
while I<>-1 do
begin
pTextLine:=pText.TextLine;
if pTextLine<>nil then
if pTextLine.TextLineType=ksTLVerticalText then pText1:=pTextLine.TextLineData as IText;
if pText1<>nil then
begin
K:=pText1.Count;
Dec(K);
while K<>-1 do
begin
pTextLine1:=pText1.TextLine[K];
if pTextLine1<>nil then
begin
S:=S+pTextLine1.Str;
J:=pTextLine1.Count;
Dec(J);
while J<>-1 do
begin
pTextItem:=pTextLine1.TextItem[J];
if pTextItem<>nil then S:=S+pTextItem.Str;
Dec(J);
end;
end;
Dec(K);
end;
end;
Dec(I);
end;
result:= S;
end;
Код рабочий, но есть одно маленькое НО, даже смешное: текст выводится двойной (например было '123' а вывелось '123123'. Сейчас буду разбираться почему :)
Еще уточнение: в таблице вертикально написано 'стальной лист' в две строки, выводит 'листлистстальнойстальной'. Разибираюсь ...
Предыдущий пример про 123 был в одну строку.
S:=S+pTextLine1.Str; убери строку, код элементарный.
Для правильного порядка надо: S:=S+pTextLine1.Str и S:=pTextItem.Str+S;
Вопрос к Sabahs - понял что надо убрать S:=S+pTextLine1.Str . А изначальная задумка использования:
while J<>-1 do
begin
pTextItem:=pTextLine1.TextItem[J];
if pTextItem<>nil then S:=S+pTextItem.Str;
Dec(J);
end;
end;
и
if pTextLine1<>nil then
begin
S:=S+pTextLine1.Str;
J:=pTextLine1.Count;
Dec(J);
какая?
Не выйдет ли потом боком отказ от чего то? Можешь рассказать вкратце о назначении каждого блока?
Справку посмотри, там всё написано.
Хотел сказать что будет если оставлю только:
if pTextLine1<>nil then S:=pTextLine1.Str+#13+#10+S;
Это тоже работает и меньше кода. Только не понятно на какие грабли наступаю
Или оставлю только:
if pTextLine1<>nil then
begin
J:=pTextLine1.Count;
Dec(J);
while J<>-1 do
begin
pTextItem:=pTextLine1.TextItem[J];
if pTextItem<>nil then S:=pTextItem.Str+#13+#10+S;
Dec(J);
end;
Что будет и то и то работает по отдельности. В справке все настолько сухо, что чайнику такому как я непонятно.
Вам, Sabahs, огромная благодарность за помощь!!!!! Когда там конкурс среди форумчан, буду голосвать за Вас!!!
Как кстати лучше обращаться на ВЫ или на ТЫ ? :)
end;
Разница в том, что текст состоит из строк, строка может содержать разный текст, жирный, курсив, разный шрифт и т.д.
В справке вполне понятно написано.
Кажется понял, если не нужно вытаскивать составляющие строки по отдельности для их раздельной обработки, то можно брать строку целиком. В любом случае код с чтением по составляющим возможно пригодится в будущем. В любом случае наша с Вами беседа полезна не только для меня, но и для всех читающих эту ветку, в т.ч чайникам. Так как в справке по API не хватает "жизненных" примеров, и поймет ее сразу только высококлассный специалист. Спасибо Вам!
Я в таблице организовывал чтение ячеек по номеру строки и столбца. Тут пришла мысль: возможно ли чтение необходимых ячеек рчным выделением или предварительно выделенного диапазона ячеек? Если да, то через ISelectManager ? Я конечно еще не разобрался в причине нежелания интерфейса iKompasDocument2D1 подключаться. Но думаю вот-вот решу эту проблему. Поэтому сразу заглядываю вперед. В общем если считывание выделенных ячеек возможно, то как?
Тут экспериментировать нужно, т.к. таблица сама сложный составной объект, не считая, что ячейка может тоже содержать составные объекты, нужно смотреть, что выдаст ISelectManager в массив.
Sabahs, у тебя какая версия КОМПАСа ? У меня 13-ая. Я тут решил 30-дневку 15-й версии постаить, даже в ней твой пример выдает "Interface not supported" . Может дело в Delphi, где-нибудь какую-нибудь галочку надо поставить или что то в этом духе?
P.S. Программы,написанные на Delphi на API7, успешно работавшие на 13-ке, вдруг престали работать - даже при старте выдается то же "Interface not supported". Проги на API5 написанные на VB работают на ура. Речь про 32-битку. Походу что то поменялось в API7 что даже подключаться как следует не хочет - создается теневой процесс Компаса при запущенном.
P.P.S Кстати не знаешь почем проги компилированные Delphi весят так много - у меня приложение 12МБ, то же самое с VB - около 0,1 МБ.? Это как-то решается?
V15 и V13 отличаются, модули Компаса на новые заменили?
Версия Компаса у меня, всегда самая последняя.
Конечно заменил. API7 конечно вещь хорошая, но ненадежная. Вообще может я что то упустил, в плане подключения модулей? Как все надо правильно делать?
Я ненадёжности API7 не замечал, работает надёжно на все 100%.
Из последнего прикрепленного проекта - винегрет, иначе я назвать не могу, по убирать все модули Компаса оставив ksApi7 и ksConstTLB, модуль ksAuto вообще не должен подключаться для exe, иначе потянет все dll Компаса, т.е. модули должны подключаться только те, что нужны. По убирать в проекте все лишние объявленные переменные и работать на нормальных интерфейсах, а не Disp-интерфейсах.
Где в Unit1 используются подключенные модули Компаса, зачем они там?
Щас попрбовал запустить программу (которая не хотела работать на 30-дневках 14-й и 15-й под Win8) на компе с 14-й версией но под Win7 - на удивление никаких ошибок. Может проблема в том что на компе где Delphi установлена Win8 ? Как решить эту проблему если дело в этом, без переустновки винды или Delphi на Win7?
На счет винегрета - почищу - посмотрю что получится.
Win8 точно не виновата.
Неужели дело в Delphi XE5 ? Или железо?
Среда тоже не виновата.
Убрал лишние модули из Вашего проекта и отредактировал:
- function InitCMPS(): bool;//Активация КОМПАСа
- procedure OpenDOC(Fname: string);//Открыть документ
PS. Инициализация работает нормально.
Вроде бы все сделал как было сказано. Но все равно вылазит "Интерфейс не поддерживается". И на дополнительном 2D1 вылазит значение nil. Может что недоизменил?
Я писал про инициализацию, а не нажимание на кнопки.
У Вас нет проверок, и т.д.
Во вложении файлы из архива "Позиции 3", на работе время оставалось и что то серьёзное начинать было бессмысленно, я от рихтовал procedure RENM(OldStr,NewStr: widestring); на предмет вылета, без вникания в суть кода, дальше сами.
Спасибо. Позже проверю заработает ли. На первый взгляд вижу что в процедуре RENM добавилась проверка интерфейсов pKompasDocument2D и pKompasDocument2D1 на равенство нулю (nil). Отсюда появляется вопросе: Если как у меня будет pKompasDocument2D1 = ni, как показывает отладчик, то просто не будет работать остальная часть процедуры. Или я не прав и в случае проверки pKompasDocument2D1 не будет равен nil ?
P.S. На другом компе с WIN7 тоже вылазит у скомпилированной программы ошибка поддержки интерфейса pKompasDocument2D1 .
P.P.S. Позже поробую реализовать подключение на Visual Basic 6. Постморим будет ли там ошибка.
Текст исправлений.
Жутко стыдно, не заметил как то сразу ))))))
Мысль появилась. Может это антивирус блокирует обращение к интрефейсу при компилияции или после при работе программы? Хотя может и дело в коде было - позже проверю.
Антивирус не виноват, см. рисунок - код, что у Вас был.
Если ksDoc = nil, соответственно pKompasDocument2D и pKompasDocument2D1 будут равны nil, и на строке: pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager; программа закончит своё существование.
Судя по показаниям отладчика у меня было:
ksDoc <> nil (были каие то цифры и буквы)
pKompasDocument2D<>nil (тоже самое)
и pKompasDocument2D1=nil
Если программа в 100% буде тзавершать сове сущ-ие если pKompasDocument2D1=nil, то чем мне это поможет? Проще ведь вообще тогда убрать эту строку и забыт ьпро этот интерфейс, не так ли?
Есть альтернативные способы подключения этого интерфейса?
Если pKompasDocument2D<>nil, то не может быть pKompasDocument2D1=nil.
У меня как то получалось что может :) Потом небольшое видео пришлю чтоб доказать )
Ты прав - антивирус ни причем. То чем я говорил на видео по размеру протиснуться не могу. ....2D не равен nil, а происходящий от него ..... 2D1 равен. Скажи как тебе его прислать?
Прикрепленный файл не качай - это часть раздробленного архива с видео. Думал влезу в начале. Удалить уже не могу.
Точку останова поставьте, где отметил и функцию procedure RENM(OldStr,NewStr: widestring); замените, в месте, где обвёл.
По второму видео, Вы не дошагали до точки останова, хотя похоже, что равен nil.
У Вас до этого, на данной системе Компас стоял ниже 12 версии?
Не могу понять что от меня требуется на третьем скриншоте
Цитата: Sabahs от 25.04.14, 18:47:26
Точку останова поставьте, где отметил и функцию procedure RENM(OldStr,NewStr: widestring); замените, в месте, где обвёл.
По второму видео, Вы не дошагали до точки останова, хотя похоже, что равен nil.
У Вас до этого, на данной системе Компас стоял ниже 12 версии?
Не помню, но вряд ли стоял после переустновки винды.
Как пользоваться отладчиком http://yadi.sk/d/UBBDMncwNEfkB
Новая проблема появилась. Добавление вертикального текста с помощью pCellText.AddTextLine(ksTLVerticalText,'456');
работает только для одной строки вертикального текста, для многострочного вертикального это не работает. Появляется лишь то что было добавлено самым первым, остальное игнорируется. Как быть?
Нежели никто не знает как добавить 2 и более строки вертикального текста в одну ячейку таблицы?
Вы для начала поделитесь, каким образом Вы пытались это сделать(полный код для работы с текстом), какие варианты пробовали?
Конечно. Вот текст:
procedure RENTable();//Чтение таблицы
var
I,J, L, RW,CL:integer;
begin
pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
pViews := pViewsAndLayersManager.Views;
for I := 0 to pViews.Count-1 do
begin
pView := pViews.ViewByNumber;
pView.Current := true;
pDrawingContainer := pView as iDrawingContainer;
pSymbols2DContainer := pView as iSymbols2DContainer;
pDrawTables:= pSymbols2DContainer.DrawingTables;
for J := 0 to pDrawTables.Count-1 do
begin
pDrawTable:= pDrawTables.Item[J] as IDrawingTable;
pTable:= pDrawTable as ITable;
if pTable<>nil then
begin
for RW := 0 to pTable.RowsCount-1 do
begin
for CL := 0 to pTable.ColumnsCount-1 do
begin
pCell:= pTable.Cell[RW,CL];
if pCell<>nil then
begin
pCellText:=pCell.Text as IText;
if pCellText<>nil then
begin
if pCellText.Str<>'@' then
begin
SourceStr:= pCellText.Str;
pCellText.Str := REPTEXT(SourceStr);
end
else
begin
READVERTICAL(pCellText);
pCellText.Clear;
for L := 0 to Length(MS)-1 do
begin
MS[L]:=REPTEXT(MS[L]);
pCellText.AddTextLine(ksTLVerticalText,MS[L]);
end;
end;
pDrawTable.Update;
end;
end;
end;
end;
end;
end;
end;
pDrawTable:=nil;
pDrawTables:=nil;
end;
procedure READVERTICAL(pTxt : IText);
var
I,K : integer;
S : Widestring;
pText1 : IText;
pTextLine1:ITextLine;
pTextItem:ITextItem;
begin
I:=pTxt.Count;
Dec(I);
S:='';
while I<>-1 do
begin
pTextLine:=pTxt.TextLine;
if pTextLine<>nil then
if pTextLine.TextLineType=ksTLVerticalText then pText1:=pTextLine.TextLineData as IText;
if pText1<>nil then
begin
K:=pText1.Count;
Setlength(MS,K);
Dec(K);
while K<>-1 do
begin
pTextLine1:=pText1.TextLine[K];
if pTextLine1<>nil then
begin
MS[K]:=pTextLine1.Str;
end;
Dec(K);
end;
end;
Dec(I);
end;
end;
В общем вот эта строка кода только одну строку вертикального текста добавляет, все что дальше идет в ту же ячейку игнорируется.
pCellText.AddTextLine(ksTLVerticalText,MS[L]);
Какие варианты пробовал? Уже не помню к сожалению - действовал шустро и стихийно, быстро менял, не сохраняя. Да и уже несколько дней прошло.
Вообще, нужно ячейку до конца отрабатывать, т.е. узнать полный состав и его менять, моё мнение, т.к. не проверял и желанием проверять не горю.
Что значит "ячейку до конца отрабатывать"?
Всё вставляет, красным обвёл структуру текста.
Если нужен текст, как показан на второй картинке, то у него структура другая.
Да мне нужен как на второй картинке. Можете код процедуры выложить, а то на скрине много что "загорожено" и не видно?
Как на перовй у меня тоже не получился. Второе обращение игонировалось, хотя может Update надо было следом а не вне цикла проводить/
Я код не писал, а на картинке, по моему четко видно(смотри структуру текста), что вертикальный текст вставлен один раз и в нём две строки.
А как тебе удалсоь вставить 2 строки, если код не писал? Хоть что то наверно все равно поменял? Просто на скриен половина кода скрыта от глаз.
Вставил вручную, чтобы структуру текста посмотреть.
Полный текст кода давал в этом http://forum.ascon.ru/index.php/topic,24881.msg191330.html#msg191330 сообщении, что ещё нужно?
Можно и программно.
Не хотит работать, хотя все сделал как на скриншотах. Что то не везет мне с API7 .... :(
Вы код показывать не забывайте, я не экстрасенс.
Вот:
procedure RENTable();//Чтение таблицы
var
I,J, L, RW,CL:integer;
//FCX : IText;
Stroka: widestring;
begin
pViewsAndLayersManager := pKompasDocument2D.ViewsAndLayersManager;
//if pKompasDocument2D1<>nil then pSelectionManager := pKompasDocument2D1.SelectionManager;
pViews := pViewsAndLayersManager.Views;
for I := 0 to pViews.Count-1 do
begin
pView := pViews.ViewByNumber;
pView.Current := true;
pDrawingContainer := pView as iDrawingContainer;
pSymbols2DContainer := pView as iSymbols2DContainer;
pDrawTables:= pSymbols2DContainer.DrawingTables;
for J := 0 to pDrawTables.Count-1 do
begin
pDrawTable:= pDrawTables.Item[J] as IDrawingTable;
pTable:= pDrawTable as ITable;
if pTable<>nil then
begin
for RW := 0 to pTable.RowsCount-1 do
begin
for CL := 0 to pTable.ColumnsCount-1 do
begin
pCell:= pTable.Cell[RW,CL];
if pCell<>nil then
begin
pCellText:=pCell.Text as IText;
if pCellText<>nil then
begin
if pCellText.Str<>'@' then
begin
SourceStr:= pCellText.Str;
pCellText.Str := REPTEXT(SourceStr);
end
else
begin
READVERTICAL(pCellText);
pCellText.Clear;
{
for L := 0 to Length(MS)-1 do
begin
MS[L]:=REPTEXT(MS[L]);
//Stroka:=Stroka+MS[L]+#13+#10;
Stroka:='dfh'+#13+#10+'abc'+#13+#10+'rty'+#13+#10;
//FCX.AddTextLine(ksTLVerticalText,'абв');
//pCellText.AddTextLine(ksTLVerticalText,MS[L]+#13+#10+'dfsf');
//pCellText.AddTextLine(ksTLVerticalText,inttostr(L));
//pCellText.AddTextLine(ksTLText,'789');
//pCellText.AddTextLine(ksTLVerticalText,'123');
//pDrawTable.Update;
//pDrawTable.Update;
end;
}
pCellText.AddTextLine(ksTLVerticalText,'dfh'+#13+#10+'abc'+#13+#10+'rty');
pDrawTable.Update;
//pCellText:=FCX;
end;
pDrawTable.Update;
end;
end;
end;
end;
end;
end;
end;
pDrawTable:=nil;
pDrawTables:=nil;
end;
То что закоментировано тоже пробовалось, но не помогло. Похоже у меня что то где то криво установлено, скорее всего Delphi.
Еще вопрос: чем отличаются от обычных Disp-интерфейсы? Может мне 2D1 подключить как Disp-интерфейс?
Во вложении процедура, меняет символы в строках вертикального текста местами, для более сложного состава текста процедура будет ещё сложнее.
На рисунке текст до и после нажатия на кнопку, при повторном нажатии вернёт вертикальный текст в первоначальное состояние.