|
27.06.2008, 16:03 | #1 |
Участник
|
Мой воариант:
1. Испотьзуюя табакс копируем имена полей в буыер обмена 2. Испоььзуя поиск и замену с регекспами меняем ^(.*)$ на table.$1 = control$2,value() или как-то так |
|
14.08.2008, 16:59 | #2 |
Moderator
|
Автонумерация полей при обмене значениями с записеподобными структурами
Вначале я хотел назвать заметку "Автонумерация колонок при выводе в Excel", так как подобные примеры - наиболее "на слуху", но по ходу сочинения текста появилось более общее название (хотя и менее ясное с первого взгляда).
Итак, о чем же речь? Наверняка многим, как и мне, приходилось писать код, подобный следующему: X++: SysExcelCells cells; ; cells.item( row, 1).value( ledgerTrans.RecId ); cells.item( row, 2).value( ledgerTrans.AccountNum ); cells.item( row, 3).value( ledgerTable.AccountName ); ..................................................... cells.item( row, 8).value( ledgerTrans.Txt ); cells.item( row, 9).value( ledgerTrans.AmountMST ); cells.item( row, 10).value( ledgerTrans.Crediting ); В принципе, нам совсем не в тягость пронумеровать такие строки вручную, когда речь идет о 10 строчках (нумерация от 1 до 10). В случае сотни строк - ситуация посложнее, но все равно преодолимая. Если неохота разминать пальцы, набивая значения от 1 до 100, то можно обратиться за помощью к Excel и сгенерировать там строчки кода при помощи формулы, имея в одной колонке номер (ячейка A1: 1), в другой значения для value (B1: ledgerTrans.RecId), а в третьей - собственно формулу (C1: ="cells.item(row," & A1 & ").value(" & B1 & ");"). Неприятности начинаются, когда обнаруживается, что в уже написанный код необходимо добавить еще одну "номерную" строку в начало (середину) или поменять строки местами. Особенно "ужасна" ситуация с началом, когда требуется перебивание всех имеющихся номеров: 1 надо перебить на 2, 2 - на 3, 3 - на 4 и т.д. И вот в один прекрасный день, копаясь в коде от нашего поставщика решения - компании GMCS, я обнаружил в схожей ситуации вывода в Excel милейшее решение проблемы. Из серии тех, до которых сам никогда не додумаешься просто потому, что никогда не задумаешься, пока не увидишь у другого. Маленькое лирическое отступление. Мне рассказали историю про человека, который частенько оставался у знакомых в гостях на ночь и неудобно спал на маленьком диване, свернувшись калачиком. Через год он (и хозяева!) случайно узнали, что диван, оказывается, раскладной... Увидев этот код, я испытал примерно такое же ощущение "через год" X++: SysExcelCells cells; int currNum = 0; int nextNum() { currNum++; return currNum; } ; cells.item( row, nextNum() ).value( ledgerTrans.RecId ); cells.item( row, nextNum() ).value( ledgerTrans.AccountNum ); cells.item( row, nextNum() ).value( ledgerTable.AccountName ); ............................................................. cells.item( row, nextNum() ).value( ledgerTrans.Txt ); cells.item( row, nextNum() ).value( ledgerTrans.AmountMST ); cells.item( row, nextNum() ).value( ledgerTrans.Crediting) ); Хотел было здесь остановиться, да вспомнил о еще одной "тягомотине". Это уже точно только для Excel и только для тех ситуаций, когда разработчик предпочитает работать с буквенными обозначениями ячеек. При использовании класса ComExcelDocument_RU решение по аналогии c nextNum может выглядеть как-то вот так: X++: static void test_nextCell(Args _args) { ComExcelDocument_RU doc = new ComExcelDocument_RU(); int currCol = 0; int currRow = 1; str nextCell() { currCol++; return ComExcelDocument_RU::numToNameCell(currCol, currRow); } ; doc.NewFile(); /* doc.InsertValue('A1', 10); doc.InsertValue('B1', 20); doc.InsertValue('C1', 30); doc.InsertValue('D1', 40); */ doc.InsertValue( nextCell(), 10); doc.InsertValue( nextCell(), 20); doc.InsertValue( nextCell(), 30); doc.InsertValue( nextCell(), 40); doc.finalize(); } P.S. 04.03.09. Иногда бывает нужно нумеровать поля несколько раз внутри метода (например, первый раз при создании структуры, а затем при записи в нее). В этом случае нужно позаботиться о своевременном обнулении счетчика (currNum = 0) при повторном проходе по полям структуры. Чтобы не выносить обнуление в отдельный оператор, можно несколько усовершенствовать функцию nextNum, добавив необязательный параметр "начать с". В этом случае в первой строке, где используется nextNum, нужно будет явно указать стартовый номер (обычно это 1), а в последующих строках применять nextNum без параметров: X++: SysExcelCells cells; int currNum = 0; int nextNum(int _beginFrom = 0) { if (prmIsDefault(_beginFrom)) currNum++; else currNum = _beginFrom; return currNum; } ; cells.item( row, nextNum(1)).value( ledgerTrans.RecId ); cells.item( row, nextNum() ).value( ledgerTrans.AccountNum ); cells.item( row, nextNum() ).value( ledgerTable.AccountName ); X++: cells.item( row, nextNum(1))... cells.item( row, nextNum() )... cells.item( row, nextNum() )... cells.item( row, nextNum(9))... cells.item( row, nextNum() )... cells.item( row, nextNum() )... Последний раз редактировалось Gustav; 04.03.2009 в 17:58. Причина: добавление |
|
08.09.2008, 18:39 | #3 |
Moderator
|
Изготовление связанных тестовых копий форм журналов и форм строк журналов
У нас в компании две развернутые Аксапты - рабочая и тестовая. Как, наверное, у многих, собственные доработки создаются на тестовой инсталляции и после успешной отладки портируются на рабочее приложение.
Иногда возникает необходимость в экспериментальных "необратимых кромсаниях" какого-нибудь объекта, например, формы. "Необратимых" в данном случае означает, что по окончании эксперимента объект не будет восстановлен к первоначальному виду и будет "полностью удален из системы" (т.е. "наигрались и подчистили за собой"). Такие эксперименты, как правило, проводятся на тестовой базе, являя собой этакое "тестирование в квадрате". Впрочем, в случае крайней необходимости их можно аккуратно проводить и на рабочей, и тогда всё сказанное ниже приобретает дополнительную значимость. Для целей создания подобных объектов в АОТ существует замечательная контекстная команда "Дублировать". После ее выполнения создается копия объекта под названием "CopyOf<НазваниеИсходногоОбъекта>". Я обычно переношу префикс в конец "<НазваниеИсходногоОбъекта>_CopyOf" и объединяю копии объектов в проект (типа "AllCopyOfs", чтобы потом легко было удалять их всех сразу). Недавно мне пришлось таким "необратимым" образом экспериментировать с формой InventJournalTable ("Складские журналы"). Быстро был создан клон InventJournalTable_CopyOf. Однако нажатие на кнопку "Строки" приводило к открытию формы, конечно же, не "<CтрокиЖурнала>_CopyOf". В зависимости от типа складского журнала, запись которого активна в данный момент в гриде формы InventJournalTable, по нажатию кнопки "Строки" открывается соответствующая форма. Меня интересовали журналы переноса, для отображения строк которых используется форма InventJournalTransfer (о чем я и прочитал в поле "Название формы" после щелчка по пункту контекстного меню "Настройка"). Дублированием был создан клон и этой формы - InventJournalTransfer_CopyOf. Но наивно было бы полагать, что при нажатии на "Строки" откроется именно она. Конечно, этого не случилось - "Настройка" по-прежнему показывала "InventJournalTransfer" безо всяких "CopyOf". Представляя, где нужно еще "подкрутить", я бодро "зашагал" в design формы журнала InventJournalTable_CopyOf и нашёл соответствующую кнопку MenuItemButton: lines. Свойство кнопки "MenuItemName" гласило: InventJournalTransLossProfit (MenuItemType = Display). Быстро найдя с помощью панели Sidax указанный пункт меню, я прочитал в свойствах: Class = Form, Object = InventJournalLossProfit (т.е. никак не нужный мне InventJournalTransfer). Цепь замкнулась, моста не было... Долго дебажить код я не стал, но в процессе понял, что на досуге надо поизучать классы JournalFormTable и InventJournalFormTable. В них срабатывает логика, которая к моменту щелчка по кнопке "Строки" подставляет в свойство "MenuItemName" нужный в данный момент пункт меню, запускающий нужную форму. Сохраненный в форме InventJournalTable дефолтный пункт меню InventJournalTransLossProfit ни на что не влияет (всё получается и с пустым значением свойства MenuItemName) и лишь сбивает с толку. Как в итоге далее я добился необходимого мне поведения задействованных объектов: 1. Прочитал пункт меню кнопки lines, перекрыв для нее метод clicked (в форме InventJournalTable_CopyOf): X++: void clicked() {; box::info(this.menuItemName()); // InventJournalTransTransfer super(); } 3. Создал копию формы, которую прочитал в свойствах этого пункта меню: InventJournalTransfer_CopyOf. 4. Прописал копию формы в копию пункта меню. 5. Окончательно придал методу clicked следующий "обманный" вид: X++: void clicked() { this.menuItemName('InventJournalTransTransfer_CopyOf'); super(); } |
|
Теги |
excel, rls, полезное, blog, axapta |
|
|