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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 14.10.2008, 13:13   #21  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
Gustav то что на картинках красное, она и есть объединенная ячейка.
Старый 14.10.2008, 13:36   #22  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Poleax Посмотреть сообщение
Как мне в аксапте вытянуть этот диапазон Range("A1").MergeArea.Address чтоб потом по нему megre сделать.
X++:
    COM         comRange, comRange1, comR;
   comR=comRange.MergeArea();
   comR.merge(); //че то не то..
Код:
Sub VBA_Macro4()
    Dim comRange As Range
    Dim comR As Range
    Dim addr As String
    
    Set comRange = Worksheets(1).Range("B2:D4")
    
    addr = comRange.Range("A1").MergeArea.Address

    'здесь Range("A1") говорит о том, что из объединенной ячейки надо взять
    'левую верхнюю ячейку диапазона - не путать с ячейкой A1 всего листа
    'без этого просто comRange.MergeArea.Address вызовет ошибку
    
    '...........................
    
    Set comR = Worksheets(1).Range(addr)
    comR.Merge
End Sub
Старый 14.10.2008, 13:58   #23  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Gustav Посмотреть сообщение
Код:
 
Sub Macro2()
    Dim rng As Range
    Set rng = Range("B2:C4")
    
    rng.Insert xlShiftDown 'где константа xlShiftDown = -4121
    rng.Copy rng.Offset(-rng.Rows.Count)
End Sub
Похоже, ларчик открывался очень просто...
Код:
 
Sub Macro22()
    Dim rng As Range
    Set rng = Range("B2:C4")
    
    If rng.MergeCells Then
        Set rng = rng.Range("A1").MergeArea
    End If
    
    rng.Insert xlShiftDown 'где константа xlShiftDown = -4121
    rng.Copy rng.Offset(-rng.Rows.Count)
End Sub
Оно??

P.S. Соответственно, добавка в метод:
X++:
if (comRange.MergeCells())
{
    comRange = comRange.Range('A1');
    comRange = comRange.MergeArea();
}
Старый 14.10.2008, 14:16   #24  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
X++:
void copyAndInsertBlock(str _bookMark, int _workSheet = 1)
{  #define.xlShiftDown(-4121)
    COM         comRange, comRange1, comR;
    int            rowsNumber, colsNumber;
    str s;
    ;

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

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

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

 //  comR=comRange.MergeArea();
//s=comRange.MergeArea.Address;

    comRange.Insert( #xlShiftDown ); 

    comRange1 = comRange.Offset(-rowsNumber);
/*
if (comRange.MergeCells())
{
    comRange1 = comRange.Range(_bookMark);
    comRange1 = comRange.MergeArea();
}
*/
    comRange.Copy(comRange1);
}
запутался с этим объединением..
Старый 14.10.2008, 14:19   #25  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Да уже всё распутано, вроде. Глаза постом выше поднимите

if (comRange.MergeCells()) перед Insert надо поставить

и не comRangeОдин, а просто comRange там - идёт преобразование comRange по ходу.

Вот ваш метод:
X++:
void copyAndInsertBlock(str _bookMark, int _workSheet = 1)
{  #define.xlShiftDown(-4121)
    COM         comRange, comRange1;
    int         rowsNumber;
    ;

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

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

    if (comRange.MergeCells())
    {
        comRange = comRange.Range('A1');
        comRange = comRange.MergeArea();
    }

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

    comRange.Insert( #xlShiftDown );  // и выше добавить: #define.xlShiftDown(-4121)
    comRange1 = comRange.Offset(-rowsNumber);
    comRange.Copy(comRange1);
}
За это сообщение автора поблагодарили: gl00mie (5).
Старый 14.10.2008, 16:12   #26  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
какой интересный код получился Gustav Спасибо. Про 'A1' конечно забавно..
Старый 14.10.2008, 17:20   #27  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Poleax Посмотреть сообщение
Про 'A1' конечно забавно..
Ага, c Excel вообще весело Любой прямоугольный диапазон из нескольких ячеек можно рассматривать как виртуальный лист внутри рабочего листа (worksheet) со своим локальным началом "A1" в левом верхнем углу этого диапазона. Причем диапазонам можно произвольно неограниченно "вкладываться" друг в друга (наверное, есть системные ограничения, я не проверял).

Поэтому запись Range("B2").Range("B2").Range("B2").Range("B2").Range("B2").Range("B2").Range("B2") - вовсе не бред сумасшедшего, а ссылка на ячейку H8:

? Range("B2").Range("B2").Range("B2").Range("B2").Range("B2").Range("B2").Range("B2").Address
$H$8
Старый 14.10.2008, 18:08   #28  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
Gustav еще немного вопросов. (конечно понимаю что я тебя замучал, но все таки)
1) comRange.Insert( #xlShiftDown ); работает так же как и comRange.Insert(); Так зачем #xlShiftDown указывать?
2) Если ли какой нибудь метод в котором можно выставить по умолчание согласие на - "Данная операция приведет к отмене объединения ячеек". Чтоб сообщение не появлялось.
3) Как можно написать еще один метод на примере copyAndInsertBlock в котором именованная ячейка переползает в нижнею без вставки новой ячейки? Т.е. есть ячейка "test" в нее вставили значение, и имя ячейки переместилось вниз (хоть скопированием данных ячейки хоть без)
Старый 14.10.2008, 18:40   #29  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Poleax Посмотреть сообщение
Gustav еще немного вопросов. (конечно понимаю что я тебя замучал, но все таки)
1) comRange.Insert( #xlShiftDown ); работает так же как и comRange.Insert(); Так зачем #xlShiftDown указывать?
2) Если ли какой нибудь метод в котором можно выставить по умолчание согласие на - "Данная операция приведет к отмене объединения ячеек". Чтоб сообщение не появлялось.
3) Как можно написать еще один метод на примере copyAndInsertBlock в котором именованная ячейка переползает в нижнею без вставки новой ячейки? Т.е. есть ячейка "test" в нее вставили значение, и имя ячейки переместилось вниз (хоть скопированием данных ячейки хоть без)
1. Для наглядности, для самодокументируемости кода

2. Есть. Выражаюсь на VBA. Надо поставить Application.DisplayAlerts = False перед Insert и потом обязательно восстановить после него (ну или после всего цикла в другом методе) Application.DisplayAlerts = True

3. Не очень понял пока. У нас она и так съезжает. Зачем это надо? Чтобы все время в "test" писать? Типа не менять оператор doc.insertValue('test', ...) ?
Старый 14.10.2008, 19:19   #30  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
Цитата:
3. Не очень понял пока. У нас она и так съезжает. Зачем это надо? Чтобы все время в "test" писать? Типа не менять оператор doc.insertValue('test', ...) ?
Ты был все таки прав на счет вставки новой строки. Глюк при использовании copyAndInsertBlock заключается в том, что вниз все данные сползают и их именнованные ячейки. А формат ячейки нет. В итоге если внизу была Шапка таблицы то она сам текст шапки сполз, а как формат был у строки так и остался а том же месте.

Победить то объединенную ячейку удалось. Но красота пропала в шаблоне.

Фокус и задание в том, что есть одна строка в ней 4 именованных ячейки. Эту строку мы размножаем и по циклу заполняем последовательно столбцы. Если проявляется новое значение в 1 столбце надо вставить строку. ну и соответственно все значения для остальных столбцов.

Идея с copyAndInsertBlock отрабатывает прекрасно кроме формата ниже лежащих строк :-(
но если вы вставляем строку то и все 4 именованных ячейки переходят на строку ниже... :-)

вызов расчета столбцов сделан отдельно. т.е. нельзя за один так цикла расчитать 4 значения для 4 ячеек. А получается что цикл пробегает только по одному столбцу.

В итоге.. решение пока где то рядом.
Старый 14.10.2008, 19:42   #31  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
Мысль в картинках...
Есть шаблон. В нем есть место где строчка. В данном примере она в Excel № 76 (картинка 1)
Нажмите на изображение для увеличения
Название: i1.PNG
Просмотров: 283
Размер:	25.8 Кб
ID:	3814

Работает вставка пока так с использованием copyAndInsertBlock и InsertRow. (картинка 2) Как видно текст сместился по всем столбцам вниз. НО форматирование осталось
Нажмите на изображение для увеличения
Название: i2.PNG
Просмотров: 304
Размер:	35.2 Кб
ID:	3815

(Картинка 3) В конечном варианте должно появится такое.
Нажмите на изображение для увеличения
Название: i3.PNG
Просмотров: 286
Размер:	37.7 Кб
ID:	3816
(Картинка 4) если использовать copyAndInsertBlock, то данные там где надо, то высота строк сползает.
Нажмите на изображение для увеличения
Название: i4.PNG
Просмотров: 257
Размер:	34.8 Кб
ID:	3817


Может у кого есть светлая мысль?

Последний раз редактировалось Poleax; 14.10.2008 в 19:55.
Старый 14.10.2008, 19:48   #32  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Размышляя, набросал тут 3 демонстрационных цикла вывода в Excel (чуть позже добавил четвертый):
X++:
static void Job_TestFourLoops(Args _args)
{
    ComExcelDocument_RU doc = new ComExcelDocument_RU();

    COM     xlApp;
    COM     wbook;
    COM     range, range1, range2;
    int     i;

    #define.xlDown(-4121)
    #define.xlPasteFormats(-4122)
    ;

    doc.NewFile();

    wbook = doc.getComDocument();
    xlApp = wbook.Parent();

// ВАРИАНТ 1
    // тестовая подготовка первой ячейки с именем и форматом
    range = xlApp.Range('B3');
    range.Name('test');
    COM::createFromObject( range.Font() ).Bold(true);

    // все время писать в test, смещая его вниз за счет вставки строк
    // и перекидывая формат на ячейку выше
    for (i=1;i<=10;i++)
    {
        doc.insertValue('test', i);
        doc.copyAndInsertRange('test');
    }
    doc.insertValue('test','');

// ВАРИАНТ 2
    // тестовая подготовка первой ячейки с именем и форматом
    range = xlApp.Range('B15');
    range.Name('test2');
    COM::createFromObject( range.Interior() ).ColorIndex(36);

    // прописывание значений
    range = xlApp.Range('test2'); // как если бы букмарк уже существовал в файле

    for (i=1;i<=10;i++)
    {
        // в цикле только пишем значения, не форматируем
        // адрес зависит от счетчика цикла
        range1 = COM::createFromVariant( range.Item(i,1) );
        doc.insertValue( range1.Address() ,i);
    }

    // в конце скопировать формат первой ячейки на все остальные
    range2 = xlApp.Range(range, range.End(#xlDown));
    range.Copy();
    range2.PasteSpecial(#xlPasteFormats);
    xlApp.CutCopyMode(false);


// ВАРИАНТ 3
    // тестовая подготовка первой ячейки с именем и форматом
    range = xlApp.Range('B27');
    range.Name('test3');
    COM::createFromObject( range.Font() ).Bold(true);
    COM::createFromObject( range.Interior() ).ColorIndex(5);

    // прописывание значений
    range = xlApp.Range('test3'); // как если бы букмарк уже существовал в файле

    range1 = range;
    for (i=1;i<=10;i++)
    {
        // в цикле только пишем значения, не форматируем
        // адрес не зависит от счетчика цикла
        doc.insertValue( range1.Address(), i);
        range1 = range1.Offset(1,0);
    }

    // в конце скопировать формат первой ячейки на все остальные
    range2 = xlApp.Range(range, range.End(#xlDown));
    range.Copy();
    range2.PasteSpecial(#xlPasteFormats);
    xlApp.CutCopyMode(false);

// ВАРИАНТ 4
    // тестовая подготовка первой ячейки с именем и форматом
    range = xlApp.Range('B39');
    range.Name('test4');
    COM::createFromObject( range.Borders() ).LineStyle(1);
    COM::createFromObject( range.Font() ).Bold(true);

    // прописывание значений
    range = xlApp.Range('test4');

    for (i=1;i<=10;i++)
    {
        // вставляем выше 'test4' строку с форматированием
        doc.copyAndInsertRangeNew('test4');

        // получаем объектную переменную для строки на одну выше 'test4'
        range1 = range.Offset(-1,0);

        // пишем в строку выше 'test4'
        doc.insertValue( range1.Address(), i);

        // range c 'test4' на каждом шаге опускается ниже и ниже
        // а range1 следует за ним строкой выше, олицетворяя собой новую вставленную строку
        // которая рождается с исходными (пустыми) значениями 'test4', а потом переписывается текущими
    }
    // в конце остается пустая строка с 'test4', которую можно удалить
    doc.deleteRow(range.Row());
}
Старый 14.10.2008, 20:25   #33  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
хм.. 3 вариант мне понравился. Сейчас с ним что то придумаю.. Спасибо за идею
Старый 14.10.2008, 23:47   #34  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Думаю, совсем должен понравиться 4-й вариант:
X++:
// ВАРИАНТ 4

    // прописывание значений
    range = xlApp.Range('test');

    for (i=1;i<=10;i++)
    {
        // вставляем выше 'test'а строку с форматированием 
        doc.copyAndInsertRange('test');

        // получаем объектную переменную для строки на одну выше 'test'а
        range1 = range.Offset(-1,0);

        // пишем в строку выше 'test'а
        doc.insertValue( range1.Address(), i);

        // range c 'test' на каждом шаге опускается ниже и ниже
        // а range1 следует за ним строкой выше, олицетворяя собой новую вставленную строку
        // которая рождается с исходными значениями 'test'а, а потом переписывается текущими
    }

    // в конце остается пустая строка с 'test', которую можно удалить
P.S. Добавил его в джоб выше.
Старый 15.10.2008, 10:15   #35  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
вчера вечерком, как и говорил покопался с 3 вариантом. Все удачно получилось.
Использовал InsertRow и смещение относительно вставки именованной ячейки. Отчет выглядит как я хотел.

Gustav С меня пиво! Спасибо за терпение!
Старый 15.10.2008, 10:39   #36  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Poleax Посмотреть сообщение
как и говорил покопался с 3 вариантом
А четвертый-то увидел? Примерно так же в итоге и получилось, наверное?
Старый 15.10.2008, 11:05   #37  
Poleax is offline
Poleax
Модератор
Аватар для Poleax
MCP
MCBMSS
Злыдни
 
1,353 / 595 (22) +++++++
Регистрация: 17.02.2005
Адрес: msk
Записей в блоге: 34
4 я увидел сегодня утром.
в третий использовал приблизительно так:
X++:
static void Job107(Args _args)
{
       ComExcelDocument_RU doc = new ComExcelDocument_RU();

    COM     xlApp;
    COM     wbook;
    COM     range, range1, range2;
    int     i,n;

    ;

    doc.NewFile();

    wbook = doc.getComDocument();
    xlApp = wbook.Parent();

// ВАРИАНТ 3
    // тестовая подготовка первой ячейки с именем и форматом

    range = xlApp.Range('B2');
    range.Name('test');

    range = xlApp.Range('test');
    n=doc.getCellName_RowNum("test");
    range1 = range;
    for (i=1;i<=10;i++)
    {
       // в цикле только пишем значения, не форматируем
        // адрес не зависит от счетчика цикла
        doc.insertRow(n,1,i);
        doc.insertValue( range1.Address(), i);
         range1 = range1.Offset(1,0);
    }
}
Старый 15.10.2008, 14:06   #38  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Poleax Посмотреть сообщение
X++:
    range = xlApp.Range('test');
    n=doc.getCellName_RowNum("test");
    range1 = range;
    for (i=1;i<=10;i++)
    {
       // в цикле только пишем значения, не форматируем
        // адрес не зависит от счетчика цикла
        doc.insertRow(n,1,i);
        doc.insertValue( range1.Address(), i);
         range1 = range1.Offset(1,0);
    }
Я немножко подправил фрагмент и упростил, отказавшись от range1 и его переопределений внутри цикла. Несмотря на зловещее выражение для вычисления адреса для insertValue, в нем используется вполне прозрачное для понимания свойство Item, которое удобно следует за счетчиком цикла. Пусть это будет вариант 5
X++:
    range = xlApp.Range('test');
    //n=doc.getCellName_RowNum("test");
    n = range.Row(); // раз уж переменную range определили, то чего так далеко за строкой лазить :)

    for (i=1;i<=10;i++)
    {
        // поменял операции местами для удобства понимания: 
        // т.е. сначала записываем значение, а потом добавляем строку ниже
        doc.insertValue(any2str(COM::createFromVariant(range.Item(i, 1)).Address()), i);
        doc.insertRow(n, 1, i);
    }

    // удаляем последнюю строку - она всегда лишняя (здесь i=11)
    doc.deleteRow(any2int(COM::createFromVariant(range.Item(i, 1)).Row()));

    // после цикла ячейка test так и остается первой (верхней) ячейкой обработанного диапазона
Теги
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, время: 19:52.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.