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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 11.08.2006, 11:00   #1  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Вызов Item() для коллекций Excel
AXAPTA 2.5 SP3

Надо при формировании отчета в Excel добавить в сформированный файл некоторую служебную информацию: кто и когда создал отчет.

В Excel для этого можно воспользоваться пунктом меню: Файл - Свойства - закладка "Прочие"

На уровне объектной модели Excel - это экземпляр коллекции CustomDocumentProperties объекта WorkBook.

Для отладки, создаю файл "Пример.xls" записываю в него одно свойство и далее пытаюсь его прочитать:

PHP код:
static void MVB_Excel_DocProperty(Args _args)
{
    
COMExcelDocument_RU     excel;
    
FileName                fileName "C:\\Пример.xls";
    
COM     comDocProp,
            
comOneProp;
    
COM     m_comDocument;
    
str     strName;
    
int     qtyProp,
            
nextI;
    ;

    
excel = new ComExcelDocument_RU();
    
excel.newFile(fileName,true);
    
m_comDocument excel.getComDocument();
    
    
comDocProp  m_comDocument.CustomDocumentProperties();
    
qtyProp     comDocProp.count();
    
info(strFmt("%1",qtyProp));

    
comOneProp comDocProp.Item(1);
    
strName comOneProp.name();
    
info(strName);

Происходит ошибка при попытке вызвать метод Item().

Цитата:
Общий сбой при вызове метода Item' COM-объекта.
Т.е. код показывает, что коллекция содержит элементы, но получить ссылку на объект внутри коллекции - не могу (!). Аналогичное сообщение при попытке добавить свойство через метод Add().

Можно ли обойти проблему?

Да, с коллекцией BuiltinDocumentProperties (это то, что на закладке "Документ" в свойствах Excel) происходит то же самое. Колекцию "вижу", объекты коллекции - нет.

Пробовал с Excel 2000 и Excel 2003 (на разных машинах) - результат одинаковый.

AXAPTA 2.5 SP3
Старый 11.08.2006, 12:29   #2  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Сталкивался с этим

А если так?
X++:
static void MVB_Excel_DocProperty(Args _args)
{
    COMExcelDocument_RU     excel;
    FileName                fileName = "C:\\Пример.xls";
    COM     doc;
    COM app;

    COM Workbook;
    COM prj;
    COM comp;
    COM module;
    COM code;
    str s;
    #define.vbext_ct_StdModule(1)
    ;

    excel = new ComExcelDocument_RU();
    excel.newFile(fileName,true);
    doc = excel.getComDocument();
    app = doc.Application();
    Workbook = app.ActiveWorkbook();
    prj = Workbook.VBProject();
    comp = prj.VBComponents();
    comp.add(#vbext_ct_StdModule);
    module = comp.item(comp.count());
    code = module.CodeModule();
    s = strfmt(
                "Sub SetDocumentProperties()\n" +
                "\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Author\").Value = \"%1\"\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Creation Date\").Value = CDate(\"%2\")\n" +
                "With ActiveWorkbook.CustomDocumentProperties\n" +
                "    .Add Name:=\"Автор\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeString, _\n" +
                "        Value:=\"%1\"\n" +
                "    .Add Name:=\"Дата создания\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeDate, _\n" +
                "        Value:=CDate(\"%2\")\n" +
                "End With\n" +
                "\n" +
                "End Sub", 
                (select UserInfo where UserInfo.id == curuserId()).Name,
                date2str(today(), 123, 2, 2, 2, 2, 4)
              );

    code.addFromString(s);
    app.Run(strfmt("%1.SetDocumentProperties", module.name()));
}
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 11.08.2006 в 12:35.
Старый 11.08.2006, 14:06   #3  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
В принципе, работает. Спасибо. Хотя это и напоминает операцию по вырезанию гланд через ж...
Старый 11.08.2006, 14:10   #4  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Оно самое
__________________
Axapta v.3.0 sp5 kr2
Старый 11.08.2006, 14:26   #5  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Владимир Максимов
Хотя это и напоминает операцию по вырезанию гланд через ж...
Зависит, на самом деле, от точки зрения. Мне, например, поначалу данную операцию напоминал любой перевод кода VBA в код X++...
Решение AndyD'а нормальное - по принципу: "разведчиков (шпионов) лучше всего вербовать из жителей той местности, где вы собираетесь производить разведку"
Старый 14.08.2006, 15:59   #6  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Для информации тем, кто пойдет тем же путем:

1) Все это добро будет работать, если это допускает политика безопасности собственно Excel. Начиная с версии XP это

Пункт меню Excel: Сервис \ Макрос \ Безопасность \ Закладка "Надежные издатели"
переключатель "Доверять доступ к Visual Basic Project"

Если этот переключатель будет выключен, то пользователь будет видет сообщение:

Цитата:
Функция VFProject возвратила код ошибки ..., что означает (unknow)
И макрос вообще не будет создан. Вылет произойдет на команде

prj = Workbook.VBProject();


2) Этот код практически один-в-один можно перенести в Word. Естесственно заменив ссылку на рабочую книгу, ссылкой на документ.

Причем в Word для элементов коллекции BuiltinDocumentProperties() можно использовать не только названия, но и константы. В Excel соответствующих констант нет, хотя, конечно, можно напрямую писать числа.
Старый 14.08.2006, 23:10   #7  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
В общем, победил я еe (Axapta'у). Сделал на интерфейсах без макросов.
Хотя этот способ можно так-же охарактеризовать как перректальный
X++:
#define.msoPropertyTypeDate(0x00000003)
#define.msoPropertyTypeString(0x00000004)
static void AndyD_Excel_DocProperty(Args _args)
{
    COMExcelDocument_RU     excel;
    FileName                fileName = "";
    COM     doc;
    COM     comDocProp,
            comOneProp;
    ComVariant  var;
    ComDispFunction funcGet;
    ComDispFunction funcSet;
    COMVariant varArg1;
    COMVariant varArg2;
    COMVariant varArg3;
    COMVariant varArg4;
    COMVariant varRet;
    ;

    excel = new ComExcelDocument_RU();
    excel.newFile(fileName,true);
    doc = excel.getComDocument();

    // ------------------ Запись в BuiltinDocumentProperties
    comDocProp  = doc.BuiltinDocumentProperties();

    funcGet = new ComDispFunction(comDocProp, "Item", COMDispContext::PropertyGet);
    varArg1 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varArg1.bStr("Author");
    varRet  = new COMVariant(COMVariantInOut::OUT_RETVAL, COMVariantType::VT_DISPATCH);
    funcGet.call(varArg1, varRet);

    comOneProp = COM::createFromInterface(varRet.iDispatch());

    funcSet = new ComDispFunction(comOneProp, "Value", COMDispContext::PropertyPut);
    varRet = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varRet.bStr((select UserInfo where UserInfo.id == curuserId()).Name + "-Builtin");
    funcSet.call(varRet);

    // Пример получения значения
    funcSet = new ComDispFunction(comOneProp, "Value", COMDispContext::PropertyGet);
    varRet = new COMVariant(COMVariantInOut::Out_retVal, COMVariantType::VT_BSTR);
    funcSet.call(varRet);
    info(varRet.bStr());

    funcGet = new ComDispFunction(comDocProp, "Item", COMDispContext::PropertyGet);
    varArg1 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varArg1.bStr("Creation Date");
    varRet  = new COMVariant(COMVariantInOut::OUT_RETVAL, COMVariantType::VT_DISPATCH);
    funcGet.call(varArg1, varRet);

    comOneProp = COM::createFromInterface(varRet.iDispatch());

    funcSet = new ComDispFunction(comOneProp, "Value", COMDispContext::PropertyPut);
    varRet = new COMVariant(COMVariantInOut::In, COMVariantType::VT_DATE);
    varRet.date(today());
    funcSet.call(varRet);

    // ------------------ Запись в CustomDocumentProperties
    comDocProp  = doc.CustomDocumentProperties();

    funcSet = new ComDispFunction(comDocProp, "Add", COMDispContext::Method);
    varArg1 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varArg1.bStr("Автор");
    varArg2 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BOOL);
    varArg2.boolean(false);
    varArg3 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_INT);
    varArg3.int(#msoPropertyTypeString);
    varArg4 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varArg4.bStr((select UserInfo where UserInfo.id == curuserId()).Name + "-Custom");
    funcSet.call(varArg1, varArg2, varArg3, varArg4);

    varArg1.bStr("Дата создания");
    varArg3.int(#msoPropertyTypeDate);
    varArg4 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_DATE);
    varArg4.date(today());
    funcSet.call(varArg1, varArg2, varArg3, varArg4);

    // Пример получения значения

    funcGet = new ComDispFunction(comDocProp, "Item", COMDispContext::PropertyGet);
    varArg1 = new COMVariant(COMVariantInOut::In, COMVariantType::VT_BSTR);
    varArg1.bStr("Автор");
    varRet  = new COMVariant(COMVariantInOut::OUT_RETVAL, COMVariantType::VT_DISPATCH);
    funcGet.call(varArg1, varRet);

    comOneProp = COM::createFromInterface(varRet.iDispatch());

    funcSet = new ComDispFunction(comOneProp, "Value", COMDispContext::PropertyGet);
    varRet = new COMVariant(COMVariantInOut::Out_retVal, COMVariantType::VT_BSTR);
    funcSet.call(varRet);
    info(varRet.bStr());
}
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: Владимир Максимов (1), Gustav (3).
Старый 15.08.2006, 10:19   #8  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Большое спасибо, а то я уже устал объяснять пользователям, что им надо установить птичку в настройках Excel или Word.

Тем более, внедренцы умудрились организовать экспорт в Excel внутри транзакции. В результате, когда VBProject() дает исключение, а Try...Catch это исключение не ловит (точнее, оно игнорируется внутри транзакции) и происходит автоматическое завершение транзакции.

Последний способ обходит блокировку VBProject и нет проблем с такой кривой органищацией работы.
Старый 15.08.2006, 15:32   #9  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Владимир Максимов
а то я уже устал объяснять пользователям, что им надо установить птичку в настройках Excel или
Word.
За Word не скажу, а в Excel'е - если вот так попробовать? (добавил чуть-чуть от себя в первый job AndyD'а)
X++:
static void MVB_Excel_DocProperty_2(Args _args)
{
    COMExcelDocument_RU     excel;
    FileName                fileName = "C:\\Пример.xls";
    COM     doc;
    COM app;
    
    
    
    COM Workbook;
    COM prj;
    COM comp;
    COM module;
    COM code;
    str s;
    
    // added by Gustav
    // ----------------------
    COM comTemp;
    str vbCrLf, alertMessage;
    // ----------------------
    
    #define.vbext_ct_StdModule(1)
    ;
    
    excel = new ComExcelDocument_RU();
    excel.newFile(fileName,true);
    doc = excel.getComDocument();
    app = doc.Application();
    
    // added by Gustav: запрос на проверку доступа к VB-проекту
    // --------------------------------------------------------
    vbCrLf = num2char(13) + num2char(10);
    alertMessage = 'Нажмите ОК и проверьте на следующем шаге включенность опции' + vbCrLf +
                    '""Доверять доступ к Visual Basic Project"" на закладке ""Надежные издатели""';
    app.ExecuteExcel4Macro('ALERT("' + alertMessage + '")');
    
    comTemp = app.CommandBars();
    comTemp = comTemp.Item('Macro');
    comTemp = comTemp.Controls();
    comTemp = comTemp.Item(3);
    comTemp.Execute();
    // --------------------------------------------------------
    
    Workbook = app.ActiveWorkbook();
    prj = Workbook.VBProject();
    comp = prj.VBComponents();
    comp.add(#vbext_ct_StdModule);
    module = comp.item(comp.count());
    code = module.CodeModule();
    s = strfmt(
                "Sub SetDocumentProperties()\n" +
                "\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Author\").Value = \"%1\"\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Creation Date\").Value = CDate(\"%2\")\n" +
                "With ActiveWorkbook.CustomDocumentProperties\n" +
                "    .Add Name:=\"Автор\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeString, _\n" +
                "        Value:=\"%1\"\n" +
                "    .Add Name:=\"Дата создания\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeDate, _\n" +
                "        Value:=CDate(\"%2\")\n" +
                "End With\n" +
                "\n" +
                "End Sub", 
                (select UserInfo where UserInfo.id == curuserId()).Name,
                date2str(today(), 123, 2, 2, 2, 2, 4)
              );
    
    code.addFromString(s);
    app.Run(strfmt("%1.SetDocumentProperties", module.name()));
    
    // added by Gustav: удаляем VBA-модуль из рабочей книги
    // --------------------------------------------------------
    comTemp = module.Collection();
    comTemp.Remove(module);
    // --------------------------------------------------------
    
}
Старый 15.08.2006, 15:56   #10  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
При всем уважении, но, боюсь, пользователи после первого десятка показов станут бить ногами.
__________________
Axapta v.3.0 sp5 kr2
Старый 15.08.2006, 16:11   #11  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Gustav
За Word не скажу, а в Excel'е - если вот так попробовать?
тогда уж проще установить соответствующие настройки безопасности с помощью групповых политик (domain group policy), чем дергать каждый раз пользователя...
Старый 16.08.2006, 00:38   #12  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Cool Отрицательный результат - тоже результат
Пытался поиграться радикально-хацкерским сочетанием Exception + SendKeys. Не покатило. Т.е. катит, но случайным образом, через раз-два, иногда наполовину. Для использования, конечно, не рекомендуется, хотя, если бы катило устойчиво, то было бы прикольно.

С другой стороны, если бы катило, то Microsoft пришлось бы изобретать новую рогатку для борьбы с таким управлением доступа к VB Project. Ибо любой, простите, дурак мог бы подобным образом поступить в своих злодейских целях...

Подозреваю, что, возможно, у них предусмотрена, какая-то случайная временная задержка на переключение этой галки "Доверять доступ к Visual Basic Project", подразумевающая именно ручное (неторопливое) переключение. Поэтому программа, как умалишенная сбрасывающая и устанавливающая этот флажок втечение долей секунды, просто отдыхает...

На память все же выкладываю джоб-попытку как отчет о проведенном исследовании:
X++:
static void MVB_Excel_DocProperty_3(Args _args)
{
    COMExcelDocument_RU     excel;
    FileName                fileName = "C:\\Пример.xls";
    COM     doc;
    COM app;
    
    COM Workbook;
    COM prj;
    COM comp;
    COM module;
    COM code;
    str s;
    
    // added by Gustav
    // ----------------------
    COM comTemp;
    str vbCrLf, alertMessage;
    int langID;
    str strSendKeys;
    boolean useTrustAccessDefault;
    
    #define.msoLanguageIDUI(2)
    // ----------------------
    
    #define.vbext_ct_StdModule(1)
    ;
    
    excel = new ComExcelDocument_RU();
    excel.newFile(fileName,true);
    doc = excel.getComDocument();
    app = doc.Application();
    
    // added by Gustav: запрос на проверку доступа к VB-проекту
    // --------------------------------------------------------
    comTemp = app.LanguageSettings();
    langID = comTemp.LanguageID(#msoLanguageIDUI); // язык интерфейса Excel 
    
    switch (langID)
    {
        case 1033:
            strSendKeys = '%TMS%T%V~'; // английский Excel (латинские буквы в стринге)
            break;
        case 1049:
            strSendKeys = '%ЕМБ%Н%В~'; // русский Excel (русские буквы в стринге)
            break;
    }
    
    useTrustAccessDefault = true;
    try
    {
        // если в исходном состоянии галка "Доверять доступ" выключена, то здесь возникает ошибка      
        comTemp = app.VBE();   
    }
    catch (Exception::Error)
    {
        useTrustAccessDefault = false;
        // корректируем ошибку установкой галки
        app.SendKeys(strSendKeys, true);
    }
    // --------------------------------------------------------
    
    Workbook = app.ActiveWorkbook();
    prj = Workbook.VBProject();
    comp = prj.VBComponents();
    comp.add(#vbext_ct_StdModule);
    module = comp.item(comp.count());
    code = module.CodeModule();
    s = strfmt(
                "Sub SetDocumentProperties()\n" +
                "\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Author\").Value = \"%1\"\n" +
                "ActiveWorkbook.BuiltinDocumentProperties(\"Creation Date\").Value = CDate(\"%2\")\n" +
                "With ActiveWorkbook.CustomDocumentProperties\n" +
                "    .Add Name:=\"Автор\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeString, _\n" +
                "        Value:=\"%1\"\n" +
                "    .Add Name:=\"Дата создания\", _\n" +
                "        LinkToContent:=False, _\n" +
                "        Type:=msoPropertyTypeDate, _\n" +
                "        Value:=CDate(\"%2\")\n" +
                "End With\n" +
                "\n" +
                "End Sub",
                (select UserInfo where UserInfo.id == curuserId()).Name,
                date2str(today(), 123, 2, 2, 2, 2, 4)
              );
    
    code.addFromString(s);
    app.Run(strfmt("%1.SetDocumentProperties", module.name()));
    
    // added by Gustav: удаляем VBA-модуль из рабочей книги
    // --------------------------------------------------------
    comTemp = module.Collection();
    comTemp.Remove(module);
    
    if (!useTrustAccessDefault)
    {
        // восстанавливаем исходное состояние галки "Доверять доступ" (т.е. выключенное)    
        app.SendKeys(strSendKeys, true);
    }
    // --------------------------------------------------------
    
}
Через некоторое время еще немножко продолжу (есть некоторые мысли). Потерпите немножко?
Старый 16.08.2006, 21:36   #13  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Thumbs up А теперь существенно положительный результат
Цитата:
Ибо любой, простите, дурак мог бы подобным образом поступить в своих злодейских целях...
Однако, как выясняется, может… И в злодейских, и в мирных!

Цитата:
Подозреваю, что, возможно, у них предусмотрена, какая-то случайная временная задержка на переключение этой галки "Доверять доступ к Visual Basic Project"
Подозреваю, что ничего такого нет, а есть просто поле ключика в Registry – AccessVBOM.


Что ж, ситуация в целом побеждена. И побеждена так, как мне хотелось – деликатно.

Под «деликатно» я в данном случае понимаю следующий алгоритм:
1. Перед нашей операцией прописывания свойств читаем текущее состояние этой опции «Доверять доступ к Visual Basic Projects», запоминаем ее в переменную, после чего принудительно включаем.
2. Открываем Excel, выполняем собственно операцию прописывания свойств в файле Excel «кодом VBA» из Аксапты, после чего закрываем Excel.
3. После закрытия Excel восстанавливаем состояние галки из переменной.

Три метода основного процесса в джобе ниже соответствуют трём вышеперечисленным шагам.

Добытые опытным путем нюансы:
1. Программное закрытие Excel в джобе важно - в противном случае 3-й шаг не имеет смысла, поскольку значение ключа в Regisrty будет перепрописано позже при закрытии Excel вручную, а в нём-то как раз галка и включена нами же на шаге 2.
2. До тех пор, пока все три шага были в едином джобе без деления на методы, шаг 3 также не имел эффекта. После разделения на методы всё получилось.
3. Есть мнение, что нюанс 2 зависит от того, где определена переменная COMExcelDocument_RU excel – во вложенном методе или в общем джобе. Получается, что для достижения эффекта на шаге 3, время жизни переменной excel должно быть ограничено рамками вложенного метода MVB_Excel_DocProperty (excel.finalize() в общем джобе не спасал).

Впрочем, если деликатность не сильно важна, а интересует только возможность врубить опцию, то это уже пожалуйста – без всяких нюансов.

Я проверял на Excel 2003 – для этой версии в имени ключа содержится подстрока «11.0». Соответственно, для Excel 2002 будет «10.0», для Excel 2000 – безразлично, так как там еще нет опции «доверять доступ».
X++:
static void MVB_Excel_DocProperty_4(Args _args)
{
    #WINAPI
     
    int trustAccess;
    int key;
    container con;
     
    void Process_Registry_Before()
    {
        // запоминание состояния флажка перед стартом Excel
        key = WinAPI::regOpenKey(#HKEY_CURRENT_USER, @'Software\Microsoft\Office\11.0\Excel\Security', #KEY_QUERY_VALUE);
        if (key)
        {
            con = WinAPI::regGetValue(key, 'AccessVBOM');
            WinAPI::regCloseKey(key);
            trustAccess = conPeek(con,1);
        }
        // включение флажка - разрешаем доступ к VBProjects
        key = WinApi::regOpenKey(#HKEY_CURRENT_USER, @'Software\Microsoft\Office\11.0\Excel\Security', #KEY_WRITE);
        if (key)
        {
            WinApi::regSetValueEx(key, 'AccessVBOM', #REG_DWORD, 1);
            WinApi::regCloseKey(key);
        }
    }
     
    void Process_Registry_After()
    {
        // восстановление состояния флажка до запуска Excel
        key = WinApi::regOpenKey(#HKEY_CURRENT_USER, @'Software\Microsoft\Office\11.0\Excel\Security', #KEY_WRITE);
        if (key)
        {
            WinApi::regSetValueEx(key, 'AccessVBOM', #REG_DWORD, trustAccess);
            WinApi::regCloseKey(key);
        }
    }
     
    void MVB_Excel_DocProperty()
    // самый первый вариант AndyD'а
    {
        COMExcelDocument_RU     excel;
        FileName                fileName = "C:\\Пример.xls";
        COM     doc;
        COM app;
     
        COM Workbook;
        COM prj;
        COM comp;
        COM module;
        COM code;
        str s;
     
        // added by Gustav
        // ----------------------
        COM comTemp;
        FileName                newFileName = "C:\\ПримерLAST.xls";
        // ----------------------
     
        #define.vbext_ct_StdModule(1)
     
        excel = new ComExcelDocument_RU();
        excel.newFile(fileName,true);
        doc = excel.getComDocument();
        app = doc.Application();
     
        Workbook = app.ActiveWorkbook();
        prj = Workbook.VBProject();
        comp = prj.VBComponents();
        comp.add(#vbext_ct_StdModule);
        module = comp.item(comp.count());
        code = module.CodeModule();
        s = strfmt(
                    "Sub SetDocumentProperties()\n" +
                    "\n" +
                    "ActiveWorkbook.BuiltinDocumentProperties(\"Author\").Value = \"%1\"\n" +
                    "ActiveWorkbook.BuiltinDocumentProperties(\"Creation Date\").Value = CDate(\"%2\")\n" +
                    "With ActiveWorkbook.CustomDocumentProperties\n" +
                    "    .Add Name:=\"Автор\", _\n" +
                    "        LinkToContent:=False, _\n" +
                    "        Type:=msoPropertyTypeString, _\n" +
                    "        Value:=\"%1\"\n" +
                    "    .Add Name:=\"Дата создания\", _\n" +
                    "        LinkToContent:=False, _\n" +
                    "        Type:=msoPropertyTypeDate, _\n" +
                    "        Value:=CDate(\"%2\")\n" +
                    "End With\n" +
                    "\n" +
                    "End Sub",
                    (select UserInfo where UserInfo.id == curuserId()).Name,
                    date2str(today(), 123, 2, 2, 2, 2, 4)
                    );
     
        code.addFromString(s);
        app.Run(strfmt("%1.SetDocumentProperties", module.name()));
     
        // added by Gustav
        // --------------------------------------------------------
        // удаляем VBA-модуль из рабочей книги
        comTemp = module.Collection();
        comTemp.Remove(module);
     
        // сохраняем новый файл Excel
        if (WinAPI::fileExists( newFileName ))
            WinAPI::deleteFile( newFileName );
        Workbook.SaveAs( newFileName );
        // закрываем файл, выходим из Excel
        excel.closeDocument();
        app.Quit();
        // --------------------------------------------------------
     
    }
     
//======================================================================
    // основной процесс
    Process_Registry_Before();
    MVB_Excel_DocProperty();
    Process_Registry_After();
}
Сей пост можно считать дополнением для темы Axapta программирует Excel на VBA.

Последний раз редактировалось Gustav; 21.08.2006 в 15:45.
Старый 17.08.2006, 17:12   #14  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Строго говоря, в моем случае, приведенный код решением вообще не является, поскольку предполагает обязательно создание файла Excel на диске еще до его отображения. По ряду причин - это сделать невозможно.

Однако за подсказку посмотреть в реестре спасибо. Как-то забыл о такой очевидной вещи.

Мелкие добавления:

Можно автоматизировать анализ версии Excel. Правда, для этого надо создать экземпляр Excel

PHP код:
    str     strExcelVersion;
    
real    excelVersion;
    ;

    
excel = new Com("Excel.Application");
    
strExcelVersion excel.version();
    print 
strExcelVersion;
    
pause;
    return; 
Удалять этот экземпляр не обязательно. Будет удален автоматически при завершении метода, поскольку ничего внутри себя не открывает (никаких файлов)

В результате и получим "9.0", "10.0" или "11.0". Соответсвенно, можно сделать анализ на необходимость контроля.


Удалить созданный модуль можно командой

PHP код:
comp.remove(module); 
Нет необходимости в дополнительной ссылке через коллекцию module.Collection();
Старый 17.08.2006, 19:09   #15  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Скромно-забавный способ задания свойств
Цитата:
Сообщение от Владимир Максимов
Надо при формировании отчета в Excel добавить в сформированный файл некоторую служебную информацию: кто и когда создал отчет.

В Excel для этого можно воспользоваться пунктом меню: Файл - Свойства - закладка "Прочие"
Если не задаваться целью записать информацию непременно на закладку "Прочие", а ограничиться теми пятью полями на закладке "Документ", которые заполнены на прилагаемом рисунке, то можно воспользоваться до сих пор поддерживаемой в современных версиях Excel возможностью выполнения команд макроязыка версии 4.0.

Код при этом получается до безобразия компактным - всё делается одной командой:
X++:
static void MVB_Excel_DocProperty_5(Args _args)
{
    COMExcelDocument_RU     excel;
    COM     doc;
    COM app;
    
    str s;
    str Title    = 'Наше Название';
    str Subject  = 'Наша ""рогатая"" Тема';
    str Author   = 'Наш Автор (МЫ)';
    str Keywords = 'Наши Ключевые слова';
    str Comments = 'Наши Заметки';
    ;
    
    excel = new ComExcelDocument_RU();
    excel.newFile('',true);
    doc = excel.getComDocument();
    app = doc.Application();
    
    s = strfmt('SUMMARY.INFO?("%1","%2","%3","%4","%5")',
                Title, Subject, Author, Keywords, Comments);
    
    app.ExecuteExcel4Macro(s);
}
Особенностью макрокоманды "SUMMARY.INFO?", как и всех других команд с "?" на конце, является то, что по окончании процедуры пользователю всегда будет предъявлено диалоговое окно, аналогичное изображенному на рисунке (т.е. нельзя просто скрыто прописать эти 5 свойств). Для закрытия окна пользователь может нажать любую кнопку или "крестик" - это без разницы, информация уже все равно сохранена в памяти.

Можно считать эту "назойливость", также как и ограниченность набора пятью полями, платой за компактность кода. Хотя, с другой стороны, не вижу в этом ничего плохого - пользователю может даже понравиться это финальное "одобрение", тем более, что он может добавить информацию и в другие поля (и вот для их сохранения ему уже придется нажать на OK).

Теоретически существует еще команда "SUMMARY.INFO" (без "?"), предназначенная как раз для скрытого прописывания, но она почему-то не производит желаемого эффекта. Не знаю, почему. Возможно, это ограничение метода ExecuteExcel4Macro в свете современной борьбы с макровирусами (в самом Excel 4.0 10 лет назад всё работало хорошо )

Если кто заинтересуется (а там есть кое-что любопытное), то можно скачать: Excel 2000 Help File: Running Excel 4.0 Macros.
Изображения
 
Старый 17.08.2006, 19:47   #16  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Владимир Максимов
Строго говоря, в моем случае, приведенный код решением вообще не является, поскольку предполагает обязательно создание файла Excel на диске еще до его отображения. По ряду причин - это сделать невозможно.
Это создание файла обязательно только в том случае, если мы хотим соблюсти крайнюю "деликатность": у пользователя перед задачей галка была сброшена, и мы хотим по окончании задачи также ее сбросить.

Если же наша цель - только не напрягать пользователя лишним сообщением о необходимости ВКЛЮЧИТЬ эту галку, то всё замечательно. Главное - включить ее перед запуском инстанса Excel, относящегося именно к нашей задаче. Потом - да и фиг с ней, с включенной.

Если же всё же не хочется оставлять пользователя надолго со включенным состоянием по соображениям вирусной безопасности, то галку можно сбрасывать в каком-нибудь пакетном режиме, например, при включении компа или при очередном запуске Аксапты на клиенте - главное, чтобы в этот момент в системе не было ни одной запущенной копий Excel.
Теги
excel

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Исследование скорости экспорта данных из Axapta в Excel (коллективный эксперимент) Gustav DAX: База знаний и проекты 79 13.02.2014 13:18
Khue Trinh: Alternative Item Blog bot DAX Blogs 0 09.04.2009 16:05
Вызов класса по Menu Item Silphidae DAX: Программирование 9 13.02.2009 02:21
[Excel] - Несколько версий Excel на машине клиента Андре DAX: Программирование 11 07.08.2007 13:45
Говорят вышел SP2 для Axapta 3. Кто нибуть что знает на эту тему? soin DAX: Прочие вопросы 10 13.10.2003 10:43
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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