19.05.2014, 19:44 | #1 |
Участник
|
SpreadSheet for dummies
Доброго времени суток.
На форме имеется SpreadSheet 11.0, с установленным в Yes свойством AutoDeclaration. При загрузке формы в SpreadSheet подгружается и наполняется данными шаблон : X++: COM worksheets, sheet, newsheet, range, rows, newRows, cell; TextBuffer tb; Table1 table1; Table2 table2; int curRow, numRows; ; //загрузка шаблона GridExcel.XMLURL("S:\\testSpreadSheet.xml"); worksheets = GridExcel.Worksheets(); //выделем нужную строчку на шаблоне sheet = worksheets.Item(1); range = sheet.Range("A9:F9"); curRow = 9; //подсчитываем кол-во необходимых для вставки строк select count(recid) from table1; numRows = table1.RecId; //вставляем строки rows = sheet.Rows(); newRows = rows.Item( strfmt("%1:%2", curRow + 1,NumRows + curRow) ); //вставляем после выделенной строки newRows.Insert(); //копируем нужный формат newRows = rows.Item( strfmt("10:%1", NumRows + curRow) ); //куда будем копировать форматирование rows = range.EntireRow(); //откуда будем копировать форматирование rows.copy( newRows ); //заполняем подготовленные строки данными tb = new TextBuffer(); while select table1 { tb.setText( strfmt( "%1\t%2\t%3\t%4\t%5\t%6", table1.ItemName, table1.Qty, table1.PurchPrice, table1.PurchPriceAmount, table1.VendName, table1.Invoice) ); tb.toClipboard(); range.paste(); curRow++; range = sheet.range("A" + int2str(curRow ) + ":F" + int2str(curRow ) ); //переход на следующую строчку } tb.setText(""); //добавляем строчку Итого cell = range.item(1,1); cell.value2("Итого"); cell = range.item(1,4); cell.value2(strfmt( '=SUM(R[-%1]C:R[-1]C)', numRows)); //делаем шрифт строки жирным cell = range.Font(); cell.bold(true); НО стоит только захотеть проделать все те же операции в другом листе книги, скопированном с первого: X++: sheet.copy( sheet ); newsheet = worksheets.Item(1); //так как вставка нового листа происходит перед существующим range = newsheet.Range("A9:F9"); Цитата:
Метод "copy" в COM-объекте класса "_Range" возвратил код ошибки 0x800A03EC (<неизвестно>), который означает: <неизвестно>.
- необходимое кол-во строк на новый лист добавляется, они выделяются и их можно заполнить каким-либо значением из кода; На данный момент проблема "решена" копированием всех строк из шаблона в новый лист, а там уже аналогично вставляем новые строки и форматируем их. Новый лист добавляется с помощью X++: newsheet = worksheets.add(); Последний раз редактировалось sashanka; 19.05.2014 в 19:47. |
|
20.05.2014, 18:36 | #2 |
Участник
|
"На вскидку" метод EntireRow относится к активному в данный момент листу Excel (SpreadSheet). Но вновь созданный лист не является активным. Его надо либо активизировать принудительно, либо вместо метода EntireRow использовать явное указание строки через Rows().
либо так X++: sheet.copy( sheet ); newsheet = worksheets.Item(1); newsheet.select(); // Принудительно активируем лист для корректной работы EntireRow X++: //копируем нужный формат newRows = rows.Item( strfmt("10:%1", NumRows + curRow) ); //куда будем копировать форматирование // rows = range.EntireRow(); //откуда будем копировать форматирование rows = rows.Item( strfmt("%1:%2", curRow, curRow) ); //откуда будем копировать форматирование rows.copy( newRows );
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
20.05.2014, 18:50 | #3 |
Участник
|
Спасибо за ответ. Ни один из способов не подошел.
Проверила еще X++: sheet.copy( sheet );
newsheet = worksheets.Item(1); //так как вставка нового листа просиходит перед существующим
newsheet.Activate(); |
|
21.05.2014, 19:06 | #4 |
Участник
|
Кстати, может просто "мусор" остался в буфере обмена после последнего tb.toClipboard()? В смысле, первая команда rows.copy() пытается скрестить "ежа и ужа". Часть буфера от Windows загнанный в tb.toClipboard() и часть буфера от OWC через rows.copy()
Попробуй сначала сделать оба листа и только потом наполнять их данными через tb.toClipboard() + range.paste() Я бы еще поэкспериментировал с копированием без параметра. Т.е. через буфер обмена. X++: // Выделяю образцовую строку bookMark = int2str(_rowTemplate) + ":" + int2str(_rowTemplate); range = sheet.range(bookMark); // Копирую ее содержимое со всеми форматами в буфер обмена range.copy(); // Вставляю из буфера обмена в строку ниже (под выделенной) range.insert(#xlDown); X++: /* Вставка указанного количества строк, как копии одной строки шаблона _rowTemplate - номер строки, которая будет размножена (скопирована) _rowsInsert - количество строк, вставляемых ПОД указанной строкой шаблона При вставке указанным способом "раздвигается" диапазон ячеек для суммирования если вставка выполняется "внутри" диапазона формулы Для сохранения суммирования в шаблоне надо делать минимум 2 строки "деталей" (чтобы была возможность указать диапазон в формуле), а вставку выполнять после второй строки "деталей", используя эту вторую строку как шаблон */ void insertRowsAsCopy(Row _rowTemplate, Row _rowsInsert) { MSOfficeBookMark_RU bookMark; SysExcelRange sysExcelRange; Row currentRow, insertedRows; ; if (_rowsInsert < 2) { return; } // Итерационный цикл // Вставляю сначала 1, потом 2, 4, 8 и т.п. строк на последнем шаге вставляю остаток строк currentRow = 1; while (currentRow < _rowsInsert) { if (currentRow * 2 <= _rowsInsert) { insertedRows = currentRow; currentRow += insertedRows; } else { insertedRows = _rowsInsert - currentRow; currentRow = _rowsInsert; } bookMark = int2str(_rowTemplate) + ":" + int2str(_rowTemplate + insertedRows - 1); sysExcelRange = this.range(bookMark); sysExcelRange.copy(); sysExcelRange.insert(#xlDown); } // while (currentRow < _rowsInsert) /* // Прямая вставка указанного количества // По времени одинаков с итерационным циклом, но имеет недостатки // 1) Нужно физическое наличие необходимого количества пустых строк // 2) В качестве "конца листа" (последней использованной ячейки) будет удвоенное количество вставляемых строк // т.е. переход по Ctrl+End выбросит далеко за конец информационной части отчета // Выделяю нужное количество строк ПОД итоговой строкой bookMark = int2str(_rowTemplate+1)+":"+int2str(_rowTemplate+1+_rowsInsert-1); sysExcelRangeSource = this.range(bookMark); sysExcelRangeSource.comObject().cut(); // Вставляю выделенные строки перед второй строкой bookMark = int2str(_rowTemplate)+":"+int2str(_rowTemplate); sysExcelRangeTarget = this.range(bookMark); sysExcelRangeTarget.insert(#xlDown); // Выделяю образцовую строку bookMark = int2str(_rowTemplate)+":"+int2str(_rowTemplate); sysExcelRangeSource = this.range(bookMark); // Копирую образцовую строку со всеми формулами во вновь добавленные строки bookMark = int2str(_rowTemplate)+":"+int2str(_rowTemplate+_rowsInsert-1); sysExcelRangeTarget = this.range(bookMark); sysExcelRangeSource.comObject().copy(sysExcelRangeTarget.comObject()); */ }
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... |
|
22.05.2014, 14:27 | #5 |
Участник
|
Цитата:
Сообщение от Владимир Максимов
Кстати, может просто "мусор" остался в буфере обмена после последнего tb.toClipboard()? В смысле, первая команда rows.copy() пытается скрестить "ежа и ужа". Часть буфера от Windows загнанный в tb.toClipboard() и часть буфера от OWC через rows.copy()
Попробуй сначала сделать оба листа и только потом наполнять их данными через tb.toClipboard() + range.paste() Я бы еще поэкспериментировал с копированием без параметра. Т.е. через буфер обмена. X++: // Выделяю образцовую строку bookMark = int2str(_rowTemplate) + ":" + int2str(_rowTemplate); range = sheet.range(bookMark); // Копирую ее содержимое со всеми форматами в буфер обмена range.copy(); // Вставляю из буфера обмена в строку ниже (под выделенной) range.insert(#xlDown);
Если вставлять новые строки по одной то время выгрузки увеличивается в разы. Насчет вставки строк - я вроде так и делаю X++: COM worksheets, sheet, newsheet, range, rows, newRows, cell; TextBuffer tb; Table1 table1; Table2 table2; int curRow, numRows; ; //загрузка шаблона GridExcel.XMLURL("S:\\testSpreadSheet.xml"); worksheets = GridExcel.Worksheets(); //выделем нужную строчку на шаблоне sheet = worksheets.Item(1); range = sheet.Range("A9:F9"); curRow = 9; //подсчитываем кол-во необходимых для вставки строк select count(recid) from table1; numRows = table1.RecId; if( numRows <= 1 ) { return; } //вставляем строки rows = sheet.Rows(); newRows = rows.Item( strfmt("%1:%2", curRow + 1,NumRows + curRow) ); //вставляем после выделенной строки newRows.Insert(); //копируем нужный формат newRows = rows.Item( strfmt("%1:%2", curRow + 1,NumRows + curRow) ); //куда будем копировать форматирование rows = range.EntireRow(); //откуда будем копировать форматирование rows.copy( newRows ); |
|
25.05.2014, 18:34 | #6 |
Участник
|
У Вас много лишних "телодвижений" Если очистить код от лишних действий, то должно быть примерно так
X++: COM worksheets, sheet, rowTemplate, newRows; int curSheet; int curRow, numRows; worksheets = GridExcel.Worksheets(); // Сразу создаем нужное количество листов по образцу первого листа sheet = worksheets.Item(1); sheet.copy( sheet ); for (curSheet = 1; curSheet <= 2; curSheet++) { //выделем нужную строчку на шаблоне sheet = worksheets.Item(curSheet); curRow = 9; //подсчитываем кол-во необходимых для вставки строк select count(recid) from table1; numRows = table1.RecId; if (!numRows) { warning('Нет данных для вставки на листе ' + int2str(curSheet)); continue; } //вставляем строки newRows = sheet.Range(strfmt("%1:%2", curRow + 1,NumRows + curRow) ); //вставляем после выделенной строки newRows.Insert(); //копируем нужный формат rowTemplate = sheet.Range(strfmt("%1:%2", curRow, curRow) ); //откуда будем копировать форматирование rowTemplate.copy( newRows ); } // for (curSheet = 1; curSheet <= 2; curSheet++) PS: Для справки OWC SpreadSheet имеет предел в 32766 операций. Не важно каких. Например, не в состоянии вставить большее количество строк. У Вас какое значение numRows получается для второго листа?
__________________
- Может, я как-то неправильно живу?! - Отчего же? Правильно. Только зря... Последний раз редактировалось Владимир Максимов; 25.05.2014 в 18:38. |
|
Теги |
errors, spreadsheet |
|
|