Цитата:
Сообщение от
бросайте изучать 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