14.08.2008, 16:59 | #21 |
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. Причина: добавление |
|
Теги |
excel, rls, полезное, blog, axapta |
|
|