Показать сообщение отдельно
Старый 30.09.2009, 17:44   #5  
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.