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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.10.2008, 19:48   #1  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
:)
Спасибо, вопрос закрыт.

по имени ячейки берем номер строки
X++:
public int getCellName_RowNum(MSOfficeBookMark_RU bookMark, int _workSheet = 1)
{
    COM comRange,
        comWorkSheet;
    COM comApplication;

    if (m_comDocument)
    {
        comWorkSheet   = this.getWorkSheet(_workSheet);
        comApplication = m_comDocument.application();
        comWorkSheet.activate();

        if (comWorkSheet && comApplication)
        {
            comRange = comApplication.range(bookMark);
        }
    }
    return comRange.Row();
}
по имени ячейки берем номер столбца
X++:
public int getCellName_ColumnNum(MSOfficeBookMark_RU bookMark, int _workSheet = 1)
{
    COM comRange,
        comWorkSheet;
    COM comApplication;

    if (m_comDocument)
    {
        comWorkSheet   = this.getWorkSheet(_workSheet);
        comApplication = m_comDocument.application();
        comWorkSheet.activate();

        if (comWorkSheet && comApplication)
        {
            comRange = comApplication.range(bookMark);
        }
    }
    return comRange.Column();
}
и джобик для теста
X++:
static void Job104(Args _args)
{
ComExcelDocument_RU doc = new ComExcelDocument_RU();
;

    doc.open("C:\\test.xls");
    doc.insertValue("test", 100);

   info('Row='+int2str(doc.getCellName_RowNum('test')) + '  Col='+ int2str(doc.getCellName_ColumnNum('test')) );

    doc.insertClearRow(2);
    doc.insertValue("test", 200);

    doc.visible(true);
}
Старый 09.10.2008, 22:01   #2  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5803 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Если даже в самом коде явно присутствуют как минимум два ветвления, ведущие к тому, что comRange может оказаться неинициализированным, не говоря уже о том, что на листе книги Excel может отсутствовать указанная "закладка", то имеет смысл проверять перед возвратом строки/столбца, что comRange на что-то ссылается, иначе придется то и дело ловить ошибки времени выполнения "объект такой-то неинициализирован".

Последний раз редактировалось gl00mie; 09.10.2008 в 22:05.
Старый 09.10.2008, 22:43   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
О, больная тема! О, любимая мозоль!

Poleax, бросайте изучать ComExcelDocument_RU, начинайте изучать Excel!

Тогда вы будете знать, что для вставки пустой строки перед ячейкой не надо узнавать ее номер, чтобы потом скормить его методу-обертке, вставляющему i-ю строку в таблицу. Если танцевать от comRange, а не от вездесущего текстового букмарка ("test"), который на каждом шаге переводится всё в тот же comRange (который почему-то приговорен быть локальным в методах этого класса), то пустая строка перед comRange вставляется так:
Код:
comRange.EntireRow().Insert()
Это псевдокод. В реале это надо расписать, как полагается при трансляции с VBA в X++ - на двух строчках. Потом посчитайте, сколько строк лишнего кода выполнится в вашем алгоритме, перед тем как в таблице появится пустая строка.

P.S. При желании можно сократить кол-во строк до одной, если воcпользоваться последними достижениями в этой области

X++:
comEarlyBindingImitation( comRange,'EntireRow()','Insert()');
Подробности здесь: Gustav: Unsorted, или Записки DAX-дилетанта - II
Старый 10.10.2008, 12:43   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
офф-топ
Цитата:
Сообщение от Посмотреть сообщение
бросайте изучать ComExcelDocument_RU, начинайте изучать Excel
Ну, вот как раз еще один поучительный пример под горячую руку.

Это код фирменного (со слоя dis) метода из класса ComExcelDocument_RU (DAX 3.0, SP4). Я добавил несколько своих комментариев (в исходном фирменном виде метод не содержит комментариев, а также самой последней строки кода):
X++:
void copyAndInsertRange(str _bookMark, int _workSheet = 1)
{
    COM         comRange, comRange1,
                comWorkSheet;

    int         colNumber, colsNumber;
    int         rowNumber, rowsNumber;
    ;

    if (! m_comDocument)
        throw error(strFmt("@DIS6401", this.getApplicationName()));

    comRange = this.findRange(_bookMark, _workSheet);
    if (! comRange)
    {
        return;
    }

    rowNumber  = comRange.row();
    comRange1  = comRange.rows();
    rowsNumber = comRange1.count();

    // вычитаем единицу... (продолжение см. ниже)
    rowNumber  = rowNumber - 1;

    colNumber  = comRange.column();
    comRange1  = comRange.columns();
    colsNumber = comRange1.count();

/*
//  этот фрагмент кода не нужен,
//  он даже вредит, если выбрать диапазон, начинающийся со строки A

    comRange.copy();

    comRange1 = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber), _workSheet);
    if (! comRange1)
    {
        return;
    }
    comRange1.select();

    m_comApplication.cutCopyMode(false);
*/
    comRange = comRange.entireRow();
    comRange.insert();

    // следующие арифметические упражнения - без комментариев... ррррр!
    // P.S. А впрочем все-таки скажу. 
    // Если бы в начале метода исходный comRange = this.findRange(_bookMark, _workSheet)
    // был сохранен в отдельную переменную, например, comRange0, 
    // то вместо следующего ужасающего comRange = this.findRange(... достаточно было бы простого
    // comRange = comRange0 - поскольку при вставке строк перед Range его адрес автоматически переопределяется!
    comRange = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber + rowsNumber + 1) + ":" +
                              ComExcelDocument_RU::numToNameCell(colNumber + colsNumber - 1, rowNumber + 2*rowsNumber),
                              _workSheet);
    if (! comRange)
    {
        return;
    }

    comRange.copy();

    // ...чтобы потом вернуть эту вычтенную ранее единицу обратно (rowNumber + 1) :)
    comRange1 = this.findRange(ComExcelDocument_RU::numToNameCell(colNumber, rowNumber + 1), _workSheet);

    comRange1.select();

    comWorkSheet = this.getWorkSheet(_workSheet);
    if (comWorkSheet)
    {
        comWorkSheet.paste();
    }

//  а вот здесь этот оператор не помешает (при данном подходе)
    m_comApplication.cutCopyMode(false);
}
А это код нового метода, делающего ту же работу:
X++:
void copyAndInsertRangeNew(str _bookMark, int _workSheet = 1)
{
    COM         comRange, comRange1;

    int         rowsNumber;
    ;

    if (! m_comDocument)
        throw error(strFmt("@DIS6401", this.getApplicationName()));

    comRange = this.findRange(_bookMark, _workSheet);
    if (! comRange)
    {
        return;
    }

    rowsNumber = any2int(COM::createFromObject( comRange.Rows() ).Count());

    COM::createFromObject(comRange.EntireRow()).Insert();
    comRange1 = comRange.Offset(-rowsNumber);
    comRange.Copy(comRange1);
}
А это тот вид метода, к которому я призываю, чтобы наконец избавиться от элементов "защитного программирования" типа if (! m_comDocument) и if (! comRange) - не от всех, конечно, но от необоснованных:
X++:
void copyAndInsertRangeNew2(COM _comRange)
{
    COM         comRange1;
    int         rowsNumber;
    ;

    rowsNumber = any2int(COM::createFromObject( _comRange.Rows() ).Count());

    COM::createFromObject(_comRange.EntireRow()).Insert();
    comRange1 = _comRange.Offset(-rowsNumber);
    _comRange.Copy(comRange1);
}
Заметьте, что в таком виде метод вообще не нуждается в классе ComExcelDocument_RU и в статическом виде может быть помещен хоть в Global.

И в качестве постскриптума и для большей ясности - код VBA, который делает ту же работу, что и вышеприведенные методы X++:
Код:
 
Sub Macro1()
    Dim rng As Range
    Set rng = Worksheets(1).Range("B2:C4")
    
    rng.EntireRow.Insert
    rng.Copy rng.Offset(-rng.Rows.Count)
End Sub
За это сообщение автора поблагодарили: blokva (3), Poleax (2).
Теги
excel, документация, как правильно, ax3.0

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
как вывести номер строки в гриде? funnut DAX: Программирование 21 01.10.2012 16:33
Цветные строки в Grid Sergo DAX: База знаний и проекты 14 19.04.2012 10:02
При создании строки в закупке статус строки становится "Отменено" AlexUnik DAX: Функционал 4 27.09.2004 16:05
Буферные ячейки на складе - зачем? renat DAX: Функционал 16 01.04.2004 20:22
Функция "Удалить строки" Oks DAX: Функционал 1 03.07.2002 18:09
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

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

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

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