• Добро пожаловать на Форум пользователей ПО АСКОН. Пожалуйста, авторизуйтесь.
 

Уважаемые пользователи,

Хотим проинформировать вас о режиме работы регистрации на нашем сайте.

Зарегистрироваться возможно в рабочие дни, с 8:00 до 20:00 (мск).

Если у вас возникнут вопросы или потребуется дополнительная информация, не стесняйтесь обращаться к нашей службе поддержки. Вы можете связаться с нами по указанным контактным данным на нашем сайте.

Благодарим вас за понимание и сотрудничество. Мы ценим ваше терпение и стремимся предоставить вам лучший опыт использования нашего сервиса.

С уважением,
Команда Ascon

Использование в клиенте Лоцмана зарегестрированных шаблонов.

Автор galeks, 01.10.14, 17:03:18

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

galeks

Здравствуйте коллеги.
Написан клиент использующий Лоцман API. Среда разработки MS VisualStudio 2010 VC++. Клиент выполняет функции расцеховщика. В функционале клиента предусмотрена возможность получать отчеты с помощью зарегистрированных в ЛОЦМАН:Конфигураторе SQL запросов. С получением данных из SQL запросов проблем не возникает, благо соответствующие функции довольно успешно расписаны в руководстве  ЛОЦМАН API (GetInfoAboutCurrentBase, GetReport).
Проблема состоит в том, что я не знаю, как эти данные выгрузить в наработанные ранее в ЛОЦМАНЕ XLS шаблоны. Т.е. Я знаю, что в шаблонах есть  стартовый макрос :
StartMacrosLOODSMAN(Rows, cols, arrTables,
arrAttributes, RowsAttr,
arrVersion, _Optional params = "") Но я не знаю как его пользовать из VC++.
1.   Меня интересует как передать из VC++ в этот макрос результаты отчета?
2.   Какой тип данных должен передаваться этому макросу? Что это VARIANT или еще что-то другое? Если это все таки VARIANT,то какой тип данных должен хранится в нем? SAFEARRAY для массивов или должны передаваться массивы из VARIANT?
Просто создать XLS файл и перенести туда данные отчета для меня не составляет проблемы (Это запасной вариант). Хочется использовать уже наработанные шаблоны .
Пожалуйста, помогите, кто знает. Намекните, в каком направлении рыть.

Chaa

Параметры описаны в примерах отчетов, поставляемых с Лоцманом.

' Передаваемые параметры:
' Rows - количество строк в массиве arrTables
' cols - количество столбцов в массиве arrTables
' arrTables - массив с результатами SQL-запроса
' arrAttributes - массив атрибутов родительского объекта
' RowsAttr - количество строк в массиве arrAttributes
'            количество столбцов и их порядок определяется в методе СП
'            GetInfoAboutVersion[режим 2]
' arrVersion - массив параметров родительского объекта
'            состоит из 8-ми записей:
'  arrVersion[0,0] := 'inID';            arrVersion[0,1] := PDMVersion.ID;
'  arrVersion[1,0] := 'stProduct';       arrVersion[1,1] := PDMVersion.stProduct;
'  arrVersion[2,0] := 'stType';          arrVersion[2,1] := PDMVersion.stType;
'  arrVersion[3,0] := 'stVersion';       arrVersion[3,1] := PDMVersion.stVersion;
'  arrVersion[4,0] := 'stState';         arrVersion[4,1] := PDMVersion.stState;
'  arrVersion[5,0] := 'inAccessLevel';   arrVersion[5,1] := PDMVersion.Access;
'  arrVersion[6,0] := 'inLockLevel';     arrVersion[6,1] := PDMVersion.Lock;
'  arrVersion[7,0] := 'boDocument';      arrVersion[7,1] := PDMVersion.boDocument;
'
'  params - строка параметров, разделитель ';'


Все параметры VARIANT, массивы это VARIANT в котором двухмерный SAFEARRAY, в котором тоже VARIANT.
На Delphi это бы выглядело примерно так:

var
    LFileName: String;
    LApplication: OleVariant;
    LRows: OleVariant;
    LCols: OleVariant;
    LTable: OleVariant;
    LAttributes: OleVariant;
    LAttrRows: OleVariant;
    LVersionInfo: OleVariant;
    LParams: OleVariant;

    function FieldByIndex(const ADataSet: IDataSet; const AIndex: Integer): OleVariant;
    begin
        with ADataSet do
            Result := FieldValue[FieldName[AIndex]];
        if Result = Null then
            Result := '';
    end;
begin
    LRows := ADataSet.RecordCount;
    LCols := ADataSet.FieldCount;
    if LRows > 0 then
    begin
        LTable := VarArrayCreate([0, LRows - 1, 0, LCols - 1], varVariant);
        ADataSet.First();
        i := 0;
        while not ADataSet.Eof do
        begin
            for j := 0 to ADataSet.FieldCount - 1 do
                ATable[i, j] := FieldByIndex(ADataSet, j);
            Inc(i);
            ADataSet.Next();
        end;
    end;

    LAttributes := VarArrayCreate([0, LVersion.Attributes.Count - 1, 0, 8], varVariant);
    // Из GetInfoAboutVersion режим 2
    // LAttrRows := ...
    for i := 0 to LAttrRows - 1 do
    begin
        LAttributes[i, 0] := ...;
        // ...
        LAttributes[i, 8] := ...;
    end;

    LVersionInfo := VarArrayCreate([0, 7, 0, 1], varVariant);
    LVersionInfo[0, 0] := 'inID';
    LVersionInfo[0, 1] := VersionID;
    // ...
    LVersionInfo[7, 0] := 'boDocument';
    LVersionInfo[7, 1] := IsDocument;

    LParams := '';

    LFileName := ...;

    LApplication := CreateOleObject('Word.Application');
    LApplication.Visible := True;
    LApplication.Documents.Add(LFileName);
    LApplication.WordBasic.Call('StartMacrosLOODSMAN',
        LRows, LCols, LTable, LAttributes, LAttrRows, LVersionInfo, LParams);
end;

+ Благодарностей: 1

galeks


galeks

Дополнительно:

Не подскажите, как получить список шаблонов конкретно привязанных к тому или иному SQL запросу? Что то я в документации по ЛоцманAPI не смог этого найти.

Chaa

GetInfoAboutCurrentBase, режим 10 - список отчетов базы данных, режим 12 - список шаблонов отчетов.

GetInfoAboutQuery(QueryID, 1) - список шаблонов для запроса, GetInfoAboutTemplate(TemplateID, 1) - список запросов для шаблона. Эти функции не описаны в справке.
+ Благодарностей: 1

galeks


galeks

Столкнулся с следующей проблемой:
Массив данных передаваемы в стартовый макрос  в VBA приходит с индексами начинающимися с 1. Из самого ЛОЦМАНа массив приходит с индексами начинающимися с 0. В следствии этого код макроса работавший при создании отчетов в ЛОЦМАНе не работает в моей программе. При попытке обратится к  arrTables(0,0) VBA выдает ошибку: "Run-time error '9': Subscript out of range"
Сам массив передаваемый в VBA  объявлен начиная с нулевых индексов (опуская подробности):

// lRows,lCols соответственно количество строк и колонок в SQL запросе
SAFEARRAY *pSa=NULL;
SAFEARRAYBOUND  pSab[2];
pSab[0].lLbound=0;
pSab[0].cElements = lRows;
pSab[1].lLbound=0;
pSab[1].cElements = lCols;

pSa =SafeArrayCreate(VT_VARIANT,2,pSab);


Подготовка  параметров и передача в VBA:

void CRepPg2::OnXlsReport(UINT nID)
{
try{
variant_t vtRez,vtRetCode,vtError;
HRESULT hr;

vtRez= theApp.m_pLoodsman->GetTemplatePath(&vtRetCode,&vtError);
Excel::_ApplicationPtr pExcelApp;

hr = pExcelApp.CreateInstance(L"Excel.Application");
if(FAILED(hr)) throw(1);
CString strFulFilename = vtRez.bstrVal + m_mapTmplRec[nID].strPath + m_mapTmplRec[nID].strName;

pExcelApp->Workbooks->Open(strFulFilename.AllocSysString());

pExcelApp->Visible[0] = VARIANT_TRUE;
variant_t vtNameFun = L"StartMacrosLoodsman";
// m_pSaDs - содержит указатель на SAFEARRAY с данными SQL запроса
variant_t vtArrTables; vtArrTables.parray = m_pSaDs; vtArrTables.vt=VT_ARRAY | VT_VARIANT;
variant_t vtArrAttributes; vtArrAttributes.parray = m_pArrAtr; vtArrAttributes.vt = VT_ARRAY| VT_VARIANT;
variant_t vtArrVersion; vtArrVersion.parray= m_pArrVer; vtArrVersion.vt=VT_ARRAY| VT_VARIANT;
variant_t vtStr = m_strRep;

pExcelApp-> Run2(vtNameFun,m_vtRows,m_vtCols,vtArrTables,vtArrAttributes,m_vtRowsAtr,m_pArrVer,vtStr);

}
catch(int nEr)
{
switch(nEr)
{
case 1:
{
AfxMessageBox(L"Не смог создать экземпляр Excel!");
break;
}
}
}
catch(_com_error& er)
{
CString strError =L"";
strError.Format(L"_com_error:\nError       : %08lX\nErrorMessage: %s\nDescription : %s\nSource      : %s\n",
er.Error(),
        (LPCTSTR)_bstr_t(er.ErrorMessage()),
        (LPCTSTR)_bstr_t(er.Description()),
        (LPCTSTR)_bstr_t(er.Source()));
AfxMessageBox(strError);
}
}


Стартовый макрос имеет вид:

Public Sub StartMacrosLOODSMAN(Rows, cols, arrTables, arrAttributes, RowsAttr, arrVersion, _
                               Optional params = "")
Call myDraw(Rows, cols, arrTables)
End Sub
Public Sub myDraw(Rows, cols, arrTables)
', arrAttributes, RowsAttr, arrVersion)
Dim i, j, BegRows, BegCol As Integer
    BegRows = 2 'начало вывода строк в таблице
    BegCol = 1  'начало вывода колонок в таблице

    Application.Worksheets("Лист1").Select
 
    For i = 0 To Rows - 1
        For j = 0 To cols - 1

            With Worksheets("Лист1").Cells(BegRows + i, BegCol + j)
                .Value = arrTables(i, j)
                .Borders.LineStyle = xlContinuous

                If (i Mod 2) = 0 Then
                    .Interior.ColorIndex = 34
                    .Interior.Pattern = xlSolid
                End If
            End With
        Next j
    Next i
End Sub


Как добиться чтобы в VBA приходил массив с нижней границей индекса = 0?

Chaa

На первый взгляд у вас все правильно сделано. Попробуйте в C++ получить элемент массива arrTables(0,0) и посмотерть, что в нем.

galeks

Проверил:

                long lIndex[2];
lIndex[0] =0; lIndex[1]=0;
variant_t vtData;
SafeArrayGetElement(vtArrTables.parray,lIndex,(void *)&vtData);

в vtData приходят данные которые действительно соответствуют элементу массива с индексами 0,0
т.е. на входе в Еxcel имею массив с одними индексами, а внитри эти индексы меняются, увеличиваются на +1. Данные приходят все. Стоит в VBA для доступа к элементам массива использовать конструкцию .Value = arrTables(i+1, j+1) как табличка чудесным образом полностью формируется. Но автоматом такой отчет перестает работать уже в ЛОЦМАНе

Может в экселе есть какой-нибудь метод который настраивает способ интерпритации получаемых данных из SAFEARRAY?

Chaa

Цитата: galeks от 17.10.14, 09:09:47
на входе в Еxcel имею массив с одними индексами, а внитри эти индексы меняются
Скорее создается копия.

Можно такой вариант попробовать:
vtArrTables.vt = VT_ARRAY | VT_BYREF | VT_VARIANT;
vtArrTables.pparray = &m_pSaDs;

Только потом нужно будет вызвать SafeArrayDestroy(vtArrTables).

P.S.
Если уж совсем ничего не поможет, то можно так:
For i = LBound(arrTables, 1) To UBound(arrTables, 1) ...

galeks

Не помогло. Результат такойже.

Наверно всетаки придется переписавать макросы  :(