AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.05.2014, 19:44   #1  
sashanka is offline
sashanka
Участник
 
28 / 10 (1) +
Регистрация: 07.02.2013
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();
Объясните что-то я делаю не так? Шаблон прилагается
Вложения
Тип файла: zip testSpreadSheet.zip (2.6 Кб, 102 просмотров)

Последний раз редактировалось sashanka; 19.05.2014 в 19:47.
Старый 20.05.2014, 18:36   #2  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
"На вскидку" метод 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  
sashanka is offline
sashanka
Участник
 
28 / 10 (1) +
Регистрация: 07.02.2013
Спасибо за ответ. Ни один из способов не подошел.
Проверила еще
X++:
    sheet.copy( sheet );
    newsheet    = worksheets.Item(1); //так как вставка нового листа просиходит перед существующим
    newsheet.Activate();
Но все равно падает на копировании формата
Старый 21.05.2014, 19:06   #4  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Кстати, может просто "мусор" остался в буфере обмена после последнего 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);
У меня для вставки в Excel написан свой метод в классе SysExcelWorksheet. Попробуй его адаптировать под OWC SpreadSheet.

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  
sashanka is offline
sashanka
Участник
 
28 / 10 (1) +
Регистрация: 07.02.2013
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Кстати, может просто "мусор" остался в буфере обмена после последнего 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);
Последовательность действий такова:
  1. подгружаю шаблон xlt
  2. открываю лист шаблон
  3. копирую его
  4. далее начинаю заполнять новый лист данными с помощью TextBuffer
Ошибка появляется даже если 1 лист добавить копированием и попытаться туда что-то записать.

Если вставлять новые строки по одной то время выгрузки увеличивается в разы.

Насчет вставки строк - я вроде так и делаю

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  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от sashanka Посмотреть сообщение
Насчет вставки строк - я вроде так и делаю
У Вас много лишних "телодвижений" Если очистить код от лишних действий, то должно быть примерно так

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

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
palleagermark: Easy reusable method to load postal codes (zipcodes) or how to save a spreadsheet as XML Blog bot DAX Blogs 0 11.10.2013 19:11
palleagermark: XML transformation from Excel spreadsheet Blog bot DAX Blogs 0 22.11.2012 14:11
Медленное копирование данных из Spreadsheet в PivotTable PSerg DAX: Программирование 0 12.08.2009 10:19
SpreadSheet if_maks DAX: База знаний и проекты 8 22.12.2005 12:42
Использование OWC.Spreadsheet для ускорения экспорта/импорта в/из Excel. storer DAX: Программирование 24 28.03.2005 19:10

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 12:59.