|
13.02.2008, 11:15 | #1 |
Участник
|
Копирование в Excel
Здравия,
Подскажите как реализовать следующее: Есть заготовка типа шаблона по разметке вкладыша в экселе на листе2. На первый лист аксаптой sysExcelWorksheet'ом закидываются требуемые значения в уже отформатированную область. Как скопировать с листа 2 требуемое оформление на первый со сдвигом для отображения 2-го, 3-го... n-го вкладыша? То есть сдвиг сам - не проблема. Как выдернуть оформление? Заранее спасибо |
|
13.02.2008, 12:00 | #2 |
Участник
|
Что-то вроде этого:
X++: #define.xlPasteFormats(-4122) private void copyLineFormat(SysExcelWorksheet _workSheet, int _fromRow, int _toRow) { Com rangeFrom, rangeTo; str strRangeFrom, strRangeTo; strRangeFrom = ComExcelDocument_RU::numToNameCell(#colItemId, _fromRow) + ":" + ComExcelDocument_RU::numToNameCell(endCol, _fromRow); strRangeTo = ComExcelDocument_RU::numToNameCell(#colItemId, _toRow) + ":" + ComExcelDocument_RU::numToNameCell(endCol, _toRow); rangeFrom = _workSheet.cells().range(strRangeFrom).comObject(); rangeTo = _workSheet.cells().range(strRangeTo).comObject(); rangeFrom.Copy(); rangeTo.PasteSpecial(#xlPasteFormats); rangeFrom.finalize(); rangeTo.finalize(); } 1) Механизм тормозной; 2) В момент формирования отчета пользователь не может использовать накаким образом буфер обмена для других задач |
|
13.02.2008, 18:19 | #3 |
Moderator
|
Михаил Петрович, не очень понимаю, зачем нужен лист2, если на лист1 уже присутствует сформатированная область.
Выведите в нее данные для вкладыша 1. Ниже нее друг за другом выведите в неформатированном виде данные вкладышей 2...N. Далее скопируйте формат области 1 на диапазон областей 2...N. Т.е. в самом конце процесса будет нужна будет всего одна (!) операция копирования формата "маленькой" области на "большую" (кратную "маленькой" N-1 раз). Как выполнить операцию копирования - уже рассказал Raven Melancholic. P.S. ВАЖНО: при копировании следует выделять не просто область 1, а полные строки, проходящие через область 1. Соответственно вставку следует производить в полные строки, проходящие через области 2...N. В этом случае высоты строк вкладыша корректно воспроизведутся и на нижних областях. В противном случае - распространятся только шрифты, заливки, рамки и т.п. |
|
15.02.2008, 14:34 | #4 |
Участник
|
Вариант решения подобных задач сильно облегчающий жизнь разработчика:
В файле шаблона Excel делаются прямые ссылки на другой лист. Т.е. напрямую в ячейках второго листа пишется нечто вроде: Лист1!A1 Сами же данные забрасываются на первый лист. Либо в специальные ячейки, либо, сплошным списком. Если заброс данных идет сплошным списоком, то адресация на втором листе делается не к конкретной ячейке, а при помощи поисковых функций самого Excel. Например: =ЕСЛИ(ЕНД(ВПР($B27;Отгрузка!$A:$N;3;ЛОЖЬ));0;ВПР($B27;Отгрузка!$A:$N;3;ЛОЖЬ)) Здесь ищется значение на листе с именем "Отгрузка" при помощи функции ВПР() по ключу из столбца "B". Функция ЕСЛИ(ЕНД(),0,ВПР()) нужна для того, чтобы подавить вывод значения #Н/Д, если по указанному ключу ничего не найдено. Разумеется сам шаблон Excel получается значительно бОльшего размера (в байтах), его сложнее модифицировать и несколько больше времени тратится на его открытие (идет обновление связей при открытии). Однако имеем следующие преимущества:
|
|
15.02.2008, 15:35 | #5 |
Moderator
|
Владимир, от души поддерживаю!
Цитата:
Сообщение от Gustav
Для развесистых стандартных шаблонов (типа акта ОС-1) теперь тоже использую такой вывод с CopyFromRecordset. В файле шаблона создаю еще один лист, можно скрытый, на который вывожу одну строку с необходимыми данными. А в ячейках самого шаблона прописываю формулы-ссылки на ячейки этой выводимой строки. Подход родился в процессе решения задачи по пакетной печати нескольких тысяч актов ОС-1. Один CopyFromRecordset вместо многих присваиваний Range.Value(...) увеличил скорость процесса примерно в 30 раз (иначе можно было бы тихо загнуться на этой печати).
- "Бланк" - собственно сформатированный бланк, который подается на печать; в ячейках бланка находятся формулы, ссылающиеся на лист "ТекущаяСтрока" вида: =ТекущаяСтрока!B3. - "ВыгруженныеДанные" - много строк, выгруженных из Аксапты при помощи CopyFromRecordset, начиная с ячейки B2 (в первой строке, c B1 - заголовки полей для удобства); с дополнительной колонкой A "Печатать?", которая по умолчанию заполняется "единичками" (о ней ниже). - "ТекущаяСтрока - таблица вида "выгруженных данных", но только с двумя строками (ну, и с теми же заголовками полей, что и на втором листе). В первой из этих двух строк находятся формулы, ссылающиеся на лист "ВыгруженныеДанные" вида (на примере ячейки B2): =ИНДЕКС(ВыгруженныеДанные!B:B, $A$2). В ячейке $A$2 содержится номер строки, которую надо напечатать. Этот номер меняется в цикле несложным макросом. Ниже этой строки находится дополнительная строка, каждая ячейка которой ссылается на ячейку выше. Цель: замена 0 пустой строкой в тех случаях, когда отображение 0 на "Бланке" нежелательно. Формула в ячейке B3 такая: =ЕСЛИ(B2=0,"",B2) Выгрузив данные, пользователь сам решает, какие именно строчки ему надо напечатать, выставляя 0 или 1 в колонке "Печатать?", после чего кнопкой запускает макрос, который бежит по колонке А и печатает бланк для тех строк, у которых в колонке A присутствует 1. Листы, кнопка, макрос живут в файле *.xlt и при выгрузке пользователь получает своеобразное мини-АРМ для печати. |
|