Показать сообщение отдельно
Старый 10.10.2008, 12:43   #9  
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).