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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 30.09.2009, 16:51   #1  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,822 / 402 (17) +++++++
Регистрация: 23.03.2006
запишите макрос в Excel, нужные свойства вроде FitToPagesWide и FitToPagesTall
Старый 30.09.2009, 17:21   #2  
decoder is offline
decoder
Участник
Аватар для decoder
 
63 / 15 (1) ++
Регистрация: 19.12.2008
Адрес: Москва
Ок. Вот я как раз и не понимаю, как этот супермакрос будет выглядеть в Х++...
Старый 30.09.2009, 17:44   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от decoder Посмотреть сообщение
Ок. Вот я как раз и не понимаю, как этот супермакрос будет выглядеть в Х++...
Примерно так:
X++:
#define.xlDialogPageSetup(7)
static void Job210_ExcelFitToPagesDemo(Args _args)
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    COM doc;
    COM app;
    COM worksheet;
    COM pageSetup;
    COM temp;

    ;
    excel.newFile();
    doc = Excel.getComDocument();
    app = doc.Application();
    worksheet = app.ActiveSheet();

    pageSetup = worksheet.PageSetup();

    pageSetup.FitToPagesWide(2);
    pageSetup.FitToPagesTall(3);

    // это для демонстрации того, что получается
    temp = app.Dialogs();
    temp = temp.Item(#xlDialogPageSetup);
    temp.Show();

}
Но сразу скажу: РАДОВАТЬСЯ РАНО! Есть подводные камни. Запустите мой джоб, поймите что я имею в виду и продолжим...

P.S. Коллеги забыли про еще один оператор VBA. Полный фрагмент на VBA должен выглядеть так:
Код:
    With ActiveSheet.PageSetup
        .Zoom = False
        .FitToPagesWide = 2
        .FitToPagesTall = 3
    End With
И это нормально работает в Excel. А теперь попробуйте задать этот Zoom из Аксапты - оператор pageSetup.Zoom(false); вызовет ошибку... Думаем, что делать дальше...

P.P.S. Нашёл пилюлю вот здесь: http://www.ozgrid.com/forum/showthread.php?t=49644

Вместо трёх операторов делаем один:
X++:
    //// pageSetup.Zoom(false); // и так не работающий
    // pageSetup.FitToPagesWide(2);
    // pageSetup.FitToPagesTall(3);

    app.ExecuteExcel4Macro('PAGE.SETUP(;;;;;;;;;;;;{2;3})');
Остается вопрос с языком формул, разделителем списка Excel и разделителем колонок массива. Как видно, у меня язык формул английский, а оба разделителя - точка с запятой. У кого-то сработает с запятой, у кого-то с русскими буквами (щас вспомню как по-русски называется этот оператор... ПАРАМЕТРЫ.СТРАНИЦЫ - кто б сомневался )

P.P.P.S. Вот как-то так вырисовывается пример в окончательном виде с учетом всех известных на данный момент особенностей региональных настроек Excel:
X++:
#define.xlDialogPageSetup(7)
static void Job210_ExcelFitToPagesDemo(Args _args)
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    COM doc;
    COM app;
    COM temp;

    str macroFormula;
    str xlListSep   = KKu::excelListSeparator(app);
    str xlColSep    = KKu::excelColumnSeparator(app);
    str xlForLang   = KKu::excelFormulaLanguage(app);

    int fitToPagesWide =  0; // страниц в ширину
    int fitToPagesTall = 10; // страниц в высоту
    ;

    excel.newFile();
    doc = excel.getComDocument();
    app = doc.Application();

    xlListSep   = KKu::excelListSeparator(app);
    xlColSep    = KKu::excelColumnSeparator(app);
    xlForLang   = KKu::excelFormulaLanguage(app);

    macroFormula = strFmt('%1(%2{%3%4%5})',
        xlForLang=='English'?'PAGE.SETUP':'ПАРАМЕТРЫ.СТРАНИЦЫ',
        strRep(xlListSep,12),
        fitToPagesWide ? int2str(fitToPagesWide) : (xlForLang=='English'?'#N/A':'#Н/Д'),
        xlColSep,
        fitToPagesTall ? int2str(fitToPagesTall) : (xlForLang=='English'?'#N/A':'#Н/Д'));

    app.ExecuteExcel4Macro(macroFormula); // для активного в данный момент листа

    // это для демонстрации того, что получается
    temp = app.Dialogs();
    temp = temp.Item(#xlDialogPageSetup);
    temp.Show();

}
Если задать обе переменные fitToPagesWide и fitToPagesTall равными 0, то соответствующие поля "Fit to" в диалоге "Page Setup" будут пустыми и выделенной станет верхняя опция "Adjust to ... % normal size".

Для исполнения джоба выше нужны некоторые методы из моего сборника статических методов - класса KKu (мой персональный "Global"). Вот они:
X++:
// определение разделителя колонок Excel - для FormulaArray
static str excelColumnSeparator(COM _excelApplication = null)
{
    #define.xlColumnSeparator(14)
    ;
    return KKu::excelSeparator(#xlColumnSeparator, _excelApplication);
}


// Определение языка формул Excel для свойства Range.Formula
// (именно Formula, а не FormulaLocal !!!)
// подробности см. здесь:
// [url=http://www.axforum.info/forums/showthread.php?p=195646#post195646]Строка в Excel[/url]

// СПОСОБ:
// помещаем в "международное" свойство формулу на русском языке
// и проверяем последующую реакцию Excel
// по окончании проверки удаляем временные объекты
static str excelFormulaLanguage(COM _excelApplication = null)
{
    str         ret;
    COM         workbook;
    COM         range;
    COMVariant  rangeText;
    boolean     separateSession = false;
    ;

    // если сессия не передается параметром...
    if (! _excelApplication)
    {
        // ...то пробуем прицепиться к существующей
        _excelApplication = COM::getObject('Excel.Application');

        // если существующей тоже нет...
        if (! _excelApplication)
        {
            // то создаем отдельную - кратковременную - только лишь для определения языка
            _excelApplication = new COM('Excel.Application');
            separateSession = true;
        }
    }

    workbook = _excelApplication.Workbooks();
    workbook =  workbook.Add();
    range    = _excelApplication.Range('A1');

    // помещаем в "международное" свойство формулу на русском языке
    // и проверяем последующую реакцию Excel
    range.NumberFormat('0'); // на всякий случай
    range.Formula('=СУММ(1+1)');
    range.Calculate(); // на всякий случай
    rangeText = range.Text();

    if (rangeText.bStr()=='2')  // здесь ожидаются значения: #NAME? или #ИМЯ? или 2
        ret = 'Russian';
    else
        ret = 'English';

    workbook.Close(false);

    if (separateSession)
        _excelApplication.Quit();

    return ret;
}


// определение разделителя списка Excel
// нужно для диапазонов вида Range('C:C,F:F')
// можно передать Excel берем параметром из контекста задачи,
// чтобы не загружать отдельную сессию из-за единственного символа;
// а можно и не загружать
static str excelListSeparator(COM _excelApplication = null)
{
    #define.xlListSeparator(5)
    ;
    return KKu::excelSeparator(#xlListSeparator, _excelApplication);
}


// Created on 04 Авг 2009 at 16:04:57 by KKU
// поскольку уже нужно как минмиум два разделителя для Excel: списка и колонок, то делаем для них общее ядро
static str excelSeparator(int _separator, COM _excelApplication = null)
{
    SysExcelApplication xlApp;
    COMVariant          sep;
    ;

    // если сессия не передается параметром...
    if (! _excelApplication)
    {
        // ...то пробуем прицепиться к существующей
        _excelApplication = COM::getObject('Excel.Application');

        // если существующей тоже нет...
        if (! _excelApplication)
        {
            // то создаем отдельную - кратковременную - только лишь для определения разделителя
            xlApp = SysExcelApplication::construct();
            _excelApplication = xlApp.comObject();
        }
    }

    sep = _excelApplication.International(_separator);

    return sep.bStr();
    // если была создана отдельная кратковременная, то она автоматически закроется
}
Уфф... Всё! Поехал домой болеть за ЦСКА против Бешикташа

Последний раз редактировалось Gustav; 30.09.2009 в 19:31.
Старый 30.09.2009, 19:53   #4  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
ХА-ХА-ХАААА... А вообще всё было проще!

COMVariant для Zoom!!

X++:
#define.xlDialogPageSetup(7)
static void Job211(Args _args)
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    COM doc;
    COM app;
    COM worksheet;
    COM pageSetup;
    COM temp;
    COMVariant cv = new COMVariant();

    ;
    excel.newFile();
    doc = Excel.getComDocument();
    app = doc.Application();
    worksheet = app.ActiveSheet();

    pageSetup = worksheet.PageSetup();

    cv.boolean(false);
    pageSetup.Zoom(cv);
    pageSetup.FitToPagesWide(2);
    pageSetup.FitToPagesTall(3);

    // это для демонстрации того, что получается
    temp = app.Dialogs();
    temp = temp.Item(#xlDialogPageSetup);
    temp.Show();
}
Правда, значение comVariant.noValue() - на случай пустого значения полей "Fit to" - что-то пока не получается передать в FitToPagesWide или в FitToPagesTall...

Последний раз редактировалось Gustav; 30.09.2009 в 20:14.
За это сообщение автора поблагодарили: Alenka (1), zelibobis (1), decoder (1).
Старый 30.09.2009, 20:19   #5  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
PS: О! Уже сам догадался
Ну типа, ага. Между прочим, какое-то Ваше же сообщение и вспомнил на эту тему

Владимир, а не посмотрите еще одну затыку:
Цитата:
Сообщение от Gustav Посмотреть сообщение
Правда, значение comVariant.noValue() - на случай пустого значения полей "Fit to" - что-то пока не получается передать в FitToPagesWide или в FitToPagesTall...
У меня вроде один раз получилось, а сейчас не могу воспроизвести... или показалось, что получилось...

P.S. Хотя я, наверное, допёр... Надо было внимательно читать собственную ссылку:
Цитата:
Сообщение от Gustav Посмотреть сообщение
Нашёл пилюлю вот здесь: http://www.ozgrid.com/forum/showthread.php?t=49644
И использовать не comVariant.noValue(), а тоже comVariant.boolean(false). Наверное, так будет нормально:

X++:
    int fitToPagesWide = 10;
    COMVariant cvWide = new COMVariant();

    if (fitToPagesWide)
        cvWide.int( fitToPagesWide );
    else
        cvWide.boolean( false );

    pageSetup.FitToPagesWide(cvWide);
Сейчас Аксапты под рукой нет, окончательно проверю завтра утром.

Последний раз редактировалось Gustav; 30.09.2009 в 23:54.
Старый 01.10.2009, 09:47   #6  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Проверил, работает. Выстрадался окончательный вариант:
X++:
#define.xlDialogPageSetup(7)
static void Job212(Args _args)
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    COM doc;
    COM app;
    COM worksheet;
    COM pageSetup;
    COM temp;

    int fitToPagesWide = 5; // страниц в ширину
    int fitToPagesTall = 0; // страниц в высоту, если 0, то поле пустое

    COMVariant cvZoom = COMVariant::createFromBoolean(false);
    COMVariant cvWide = fitToPagesWide ? COMVariant::createFromInt( fitToPagesWide ) 
                                       : COMVariant::createFromBoolean( false );
    COMVariant cvTall = fitToPagesTall ? COMVariant::createFromInt( fitToPagesTall )
                                       : COMVariant::createFromBoolean( false )    ;
    ;
    excel.newFile();
    doc = excel.getComDocument();
    app = doc.Application();

    worksheet = app.ActiveSheet();
    pageSetup = worksheet.PageSetup();

    pageSetup.Zoom(cvZoom);
    pageSetup.FitToPagesWide(cvWide);
    pageSetup.FitToPagesTall(cvTall);

    // это для демонстрации того, что получается
    temp = app.Dialogs();
    temp = temp.Item(#xlDialogPageSetup);
    temp.Show();
}
Старый 01.10.2009, 11:34   #7  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
И всё-таки сгодится в хозяйстве макро PAGE.SETUP
Я еще раз внимательно изучил ссылку-пилюлю: http://www.ozgrid.com/forum/showthread.php?t=49644.

Человеку, который там задает вопрос, нужно было следующее: прочитать значение процентов масштабирования после того, как ранее была применена подгонка по страницам (Fit to). Когда это делается вручную, то сначала устанавливаются значения Fit to и жмётся OK. Рабочий лист при этом должен быть с большим количеством данных, иначе эффекта масштабирования не будет - пустой лист не масштабируется. Далее повторно вызываем диалог "Page Setup" и видим, что в поле "Adjust to...% normal size" отображается конкретный процент масштабирования, который автоматически рассчитался в Excel по нашем параметрам подгонки. И пусть это значение нам и нужно получить в коде.

Отвечающий на вопрос там предлагает дважды выполнить команду PAGE.SETUP. Но мы-то вроде умеем уже и без нее устанавливать необходимые свойства. Правда, оказывается, что этого недостаточно для получения значения Zoom'а...

Не буду вдаваться в подробности, а просто приведу джоб в окончательном виде, когда мне удалось прочитать значение процентов масштабирования после подгонки, и вы сами всё увидите:
X++:
static void Job212_PageSetupReadPercent(Args _args)
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    COM doc;
    COM app;
    COM worksheet;
    COM pageSetup;
    COM temp;
    COM range;

    str macroFormula;
    str xlForLang   = KKu::excelFormulaLanguage(app);

    int fitToPagesWide = 0;
    int fitToPagesTall = 5;

    COMVariant cvZoom = COMVariant::createFromBoolean(false);
    COMVariant cvZoomNum;
    COMVariant cvWide = fitToPagesWide ? COMVariant::createFromInt( fitToPagesWide )
                                       : COMVariant::createFromBoolean( false );
    COMVariant cvTall = fitToPagesTall ? COMVariant::createFromInt( fitToPagesTall )
                                       : COMVariant::createFromBoolean( false )    ;

    void executePageSetup()
    {
        // даже "холостой" вызов PAGE.SETUP (т.е. без параметров)
        // как бы является нажатием кнопки ОК в диалоге "Page Setup"
        macroFormula = strFmt('%1()', xlForLang=='English'?'PAGE.SETUP':'ПАРАМЕТРЫ.СТРАНИЦЫ');
        app.ExecuteExcel4Macro(macroFormula);
    }
    ;

    excel.newFile();
    doc = excel.getComDocument();
    app = doc.Application();

    // заполняем лист большим количеством данных
    worksheet = app.ActiveSheet();
    range = worksheet.Range('A1:Z1000');
    range.Value2('test');

    pageSetup = worksheet.PageSetup();

    pageSetup.Zoom(cvZoom);
    pageSetup.FitToPagesWide(cvWide);
    pageSetup.FitToPagesTall(cvTall);

    // сравните с иным конечным видом диалога "Page Setup, 
    // закомментировав следующую строку
    executePageSetup();

    pageSetup.FitToPagesWide(cvZoom); // cvZoom здесь используется
    pageSetup.FitToPagesTall(cvZoom); // как носитель значения false

    // сравните с иным конечным видом диалога "Page Setup, 
    // закомментировав следующую строку
    executePageSetup();

    // читаем значение процентов масштабирования
    cvZoomNum = pageSetup.Zoom();
    box::info(strFmt('Adjust to %1 % normal size', cvZoomNum.long()));

    // это для демонстрации того, что получается
    temp = app.Dialogs();
    temp = temp.Item(#xlDialogPageSetup);
    temp.Show();
}
Запустив этот джоб в исходном виде вы получите такие картинки:

Название: PageSetup1.JPG
Просмотров: 4627

Размер: 5.8 КбНажмите на изображение для увеличения
Название: PageSetup2.JPG
Просмотров: 629
Размер:	54.0 Кб
ID:	5191

После запуска этого же джоба с закомментированными строками executePageSetup (см. в комментариях, где я прошу это сделать) картинки будут менее радостными:

Название: PageSetup3.JPG
Просмотров: 4654

Размер: 6.6 КбНажмите на изображение для увеличения
Название: PageSetup4.JPG
Просмотров: 675
Размер:	56.7 Кб
ID:	5193

Вот как-то так...

Уфф... И приятно, что ЦСКА вчера не посрамил Страну и выиграл 2:1
Теги
excel, масштаб, программно, com-объект

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Исследование скорости экспорта данных из Axapta в Excel (коллективный эксперимент) Gustav DAX: База знаний и проекты 79 13.02.2014 13:18
emeadaxsupport: How does the Export to Excel feature work under the hood? Blog bot DAX Blogs 0 07.09.2009 19:05
[Excel] - Несколько версий Excel на машине клиента Андре DAX: Программирование 11 07.08.2007 13:45
Вызов Item() для коллекций Excel Владимир Максимов DAX: Программирование 15 17.08.2006 19:47
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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