12.03.2009, 17:36 | #21 |
Moderator
|
Цитата:
Или вам нужны промежуточные "нарезанные" результаты? Ну, не удаляйте их тогда |
|
12.03.2009, 17:56 | #22 |
Участник
|
Спасибо, разобрался, к вечеру сломан мозг, знаете ли с такими конструкциями
|
|
13.03.2009, 11:25 | #23 |
Участник
|
Сегодня попробовал применить результаты на практике, вот что у меня вышло
X++: void Exec(str Path,SnQueryTableTmp SnQ) { str strValue; str strFormula; COMVariant sep; #define.xlPasteValues(-4163) #define.xlListSeparator(5) ; xlApp = new COM('Excel.Application'); xlApp.Visible(true); wbks = xlApp.Workbooks(); wbk = wbks.Add(); wkss = wbk.Worksheets(); wks = wkss.Add(); wks = wkss.Item(1); wks.Name('Итог'); rng = wks.Range('A1'); //==================================Первая вкладка======================= rstAxa = new COM('ADODB.Recordset'); flds = rstAxa.Fields(); flds.Append('Дата закрытия' ,this.adoTypeToExcel('date')); flds.Append('Отгрузочная накладная' ,this.adoTypeToExcel('str')); flds.Append('Заказ' ,this.adoTypeToExcel('str')); flds.Append('Безналичная накладная' ,this.adoTypeToExcel('str')); flds.Append('Менеджер' ,this.adoTypeToExcel('str')); flds.Append('Код клиента' ,this.adoTypeToExcel('str')); flds.Append('Дата отгрузочной накладной' ,this.adoTypeToExcel('date')); flds.Append('Город' ,this.adoTypeToExcel('str')); flds.Append('Краткое наименование' ,this.adoTypeToExcel('str')); flds.Append('Номенклатура' ,this.adoTypeToExcel('str')); flds.Append('Код дет. в спецификации' ,this.adoTypeToExcel('str')); flds.Append('Название' ,this.adoTypeToExcel('str')); flds.Append('Склад' ,this.adoTypeToExcel('str')); flds.Append('Цена ед.' ,this.adoTypeToExcel('num')); flds.Append('Себестоимость' ,this.adoTypeToExcel('num')); flds.Append('Количество' ,this.adoTypeToExcel('num')); flds.Append('Сумма по позиции' ,this.adoTypeToExcel('num')); flds.Append('Прибыль' ,this.adoTypeToExcel('num')); flds.Append('Каталожный номер' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера1' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера2' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера3' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера4' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера5' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера6' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера7' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера8' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера9' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера10' ,this.adoTypeToExcel('str')); flds.Append('Серийные номера11' ,this.adoTypeToExcel('str')); flds.Append('REF' ,this.adoTypeToExcel('str')); flds.Append('Квота' ,this.adoTypeToExcel('str')); flds.Append('Конечный клиент' ,this.adoTypeToExcel('str')); flds.Append('Номер партии' ,this.adoTypeToExcel('str')); rstAxa.Open(); // SnQ.setTmpData(SnQ); while select SnQ { sep = xlApp.International(#xlListSeparator); strFormula = strFmt('=CONCATENATE(RC[-30]%2RC[-29]%2RC[-28]%2RC[-27]%2RC[-26]%2RC[-25]%2RC[-24]%2RC[-23]%2RC[-22]%2RC[-21])', sep.bStr()); strValue = strRep(SnQ.findSerialNumbersFromWMS(SnQ), 60); rstAxa.AddNew(); // fld = flds.Item('Каталожный номер'); fld.Value(SelloutMsTable.A_PartNumber); fld = flds.Item('Дата закрытия'); fld.Value(SnQ.DeliveryDate); fld = flds.Item('Отгрузочная накладная'); fld.Value(SnQ.PickingListId); fld = flds.Item('Заказ'); fld.Value(SnQ.SalesId); fld = flds.Item('Безналичная накладная'); fld.Value(SnQ.InvoiceIdElect); fld = flds.Item('Менеджер'); fld.Value(SnQ.SalesResponsible); fld = flds.Item('Код клиента'); fld.Value(SnQ.CustAccount); fld = flds.Item('Дата отгрузочной накладной'); fld.Value(SnQ.PickingListDate); fld = flds.Item('Город'); fld.Value(SnQ.City); fld = flds.Item('Краткое наименование'); fld.Value(SnQ.NameAlial); fld = flds.Item('Номенклатура'); fld.value(SnQ.ItemId); fld = flds.Item('Код дет. в спецификации'); fld.Value(SnQ.ChosenPartNumber); fld = flds.Item('Название'); fld.Value(SnQ.ItemName); fld = flds.Item('Склад'); fld.Value(SnQ.InventLocationId); fld = flds.Item('Цена ед.'); fld.Value(SnQ.A_SalesPrice); fld = flds.Item('Себестоимость'); fld.Value(SnQ.SalesCostPrice); fld = flds.Item('Количество'); fld.Value(SnQ.Qty); fld = flds.Item('Сумма по позиции'); fld.Value(SnQ.Amount); fld = flds.Item('Прибыль'); fld.Value(SnQ.SalesProfit); fld = flds.Item('Каталожный номер'); fld.Value(SnQ.A_PartNumber); fld = flds.Item('Серийные номера1'); fld.Value(strFormula); fld = flds.Item('Серийные номера2'); fld.Value(strValue); fld = flds.Item('Серийные номера3'); fld.Value(strValue); fld = flds.Item('Серийные номера4'); fld.Value(strValue); fld = flds.Item('Серийные номера5'); fld.Value(strValue); fld = flds.Item('Серийные номера6'); fld.Value(strValue); fld = flds.Item('Серийные номера7'); fld.Value(strValue); fld = flds.Item('Серийные номера8'); fld.Value(strValue); fld = flds.Item('Серийные номера9'); fld.Value(strValue); fld = flds.Item('Серийные номера10'); fld.Value(strValue); fld = flds.Item('Серийные номера11'); fld.Value(strValue); fld = flds.Item('REF'); fld.Value(SnQ.REF); fld = flds.Item('Квота'); fld.value(SnQ.InventQuotationId); fld = flds.Item('Конечный клиент'); fld.Value(SnQ.EndPartnerCode); fld = flds.Item('Номер партии'); fld.Value(SnQ.InventBatchId); rstAxa.Update(); } cell = rng.Offset(1,0); cell.CopyFromRecordset(rstAxa); rng = wks.Range('T2:T%'); rng.FormulaR1C1( rng.Value() ); rng.Copy(); rng.PasteSpecial(#xlPasteValues); xlApp.CutCopyMode(true); rng = wks.Columns(); rng = COM::createFromVariant(rng.Item('U:AD')); rng.Delete(); rstAxa.close(); actWin = xlApp.ActiveWindow(); // actWin.FreezePanes(true); } |
|
13.03.2009, 12:05 | #24 |
Участник
|
да, и если в наборе 1 серийный номер, то результат в виде скленных одних и тех же серийных номеров
|
|
13.03.2009, 12:31 | #25 |
Moderator
|
Ой, йо... Вы не воспринимайте всё уж так буквально в моем джобе!! Там strValue пишется одинаково во все 10 колонок только для того, чтобы В РАМКАХ ПРИМЕРА чем-то их заполнить а-ля "60 серийников" - ну не генерить же мне 600 тестовых уникальных значений! Точно так же функция strRep у меня используется для формирования строки из 60 одинаковых серийников: исходная строка "1234567890123, " повторяется 60 раз. Вы же подаете на вход этой функции свою длиннющую строку, уже содержащую сотни серийников и повторяете ее 60 раз - конечно Excel'ю плохеет! Наверное, строка получается больше и 911, и 32767 символов...
Цитата:
P.S. Подозреваю, что серийники нужно сначала прочитать в массив, а потом писать в колонки: в колонку 1 - с 1-го по 60-й, в колонку 2 - с 61-го по 120-й, в колонку 3 - с 121-го по 180-й и т.д. Добавляя запятую и пробел после каждого серийника и не делая этого после последнего серийника. А можно сразу в элемент массива записывать серийник+запятую+пробел (за исключением последнего). Соответственно, если заполненных элементов массива меньше 600, то оставшиеся непрописанными элементы массива будут давать пустые строки, которые при слиянии в Excel не окажут никакого влияния на результат. Остались неясности? |
|
|
За это сообщение автора поблагодарили: Antoncheg (1). |
16.04.2009, 12:11 | #26 |
Участник
|
Коллеги, еще вопросик, внедрил данный код, работает успешно, но на машинах с английским офисом. На русском эксель выдает вместо результата формулы #ИМЯ?, попробовал заменить CONCACENATE на СЦЕПИТЬ, в русском работает (офисе), английском - нет. Возможно ли как-нибудь обойти данную ситуацию? Заранее благодарен!
|
|
16.04.2009, 13:07 | #27 |
Moderator
|
Фрагмент для превращения текста в формулы и затем в значения (типа нижеследующего) на правильный столбец настроен?
X++: rng = wks.Range('T2:T%'); rng.FormulaR1C1( rng.Value() ); rng.Copy(); rng.PasteSpecial(#xlPasteValues); xlApp.CutCopyMode(true); |
|
16.04.2009, 13:23 | #28 |
Участник
|
Да все так
|
|
16.04.2009, 14:22 | #29 |
Moderator
|
Попробуйте аналогично проверить у себя языковые настройки. Что при английском и что при русском Excel'ях выдает?
|
|
16.04.2009, 17:31 | #30 |
Moderator
|
Тема, на самом деле, интересная и до конца не решенная.
В интернете ответа пока не нашёл, но нашёл достаточно подробное описание проблемы: http://www.gotdotnet.ru/Forums/Windows/107618.aspx Цитата:
Сообщение от туда
Проблема состоит в следующем. Мне надо сформировать из проекта на C# таблицу в Excel. В ней кроме данных должны присутствовать и формулы - самые простые - Сумма. Проблема в том, что в разных версиях Excel функции называются по разному - СУММ() в русской версии, и SUM() - в английской. Мне надо, чтобы выходная таблица корректно формировалась независимо от локализации Excel'я. Среди свойств ячейки (диапазона) есть Formula и FormulaLocal. Как я полагал, в свойстве FormulaLocal хранится локализованный вариант формулы ( например, СУММ(E2:E8) ), а в Formula - независимый от локализации (то есть - SUM(E2:E8) ). Но когда я присваиваю при формировании таблицы из моей программы свойству Formula нужной ячейки значение "=SUM(E2:E8)", Excel его не понимает (экспериментирую с русской версией). Понимает только "=СУММ(E2:E8)". С русской версией Excel моя программа будет работать нормально, а как быть, если на машине пользователя стоит английская версия?
.......... (вопрошающему отвечают, но, как оказывается, не совсем удачно): Используйте свойство Formula. Присваивайте ему формулу в АНГЛИЙСКОМ варианте. Пример: Range("A10").Formula = "=SUM(A1:A9)" В этом случае свойство FormulaLocal вернет правильную локализованную версию формулы: "=СУММ(A1:A9)" для русского офиса. .......... В том то и дело, что это не работает. Я это указал в начальном письме. Если я присваиваю свойству Formula значение "=SUM(A1:A9)", то в ячейке появляется сообщение "#ИМЯ?", т.е. - формула содержит нераспознанный текст. А если я пишу макрос напрямую на VBA, не через C#, то тогда все нормально. Этот глюк не изменился и после апдейта на Office XP. Вот я и задал этот вопрос - может дело еще в чем-то. X++: static void Job161_TestFormula(Args _args) { COM xlApp = new COM ('Excel.Application'); COM wbk; COM rng; COMVariant cv; ; wbk = xlApp.Workbooks(); wbk = wbk.Add(); rng = xlApp.Range('A1'); rng.Formula('=СУММ(1+1)'); cv = rng.Text(); // здесь ожидаются значения: #NAME? или #ИМЯ? или 2 box::info(cv.bStr()); wbk.Close(false); // чтобы не оставался скрытый экземпляр Excel xlApp.Quit(); } |
|
16.04.2009, 18:15 | #31 |
Участник
|
Цитата:
Предлагаю Antoncheg'у и всем желающим поучаствовать в небольшом эксперименте, запустив следующий маленький джобик. Разыскиваются люди, у которых в боксе будет выдано значение 2.
русский офис 2007
__________________
aLL woRk aNd nO JoY MAKes jAck a dULL Boy |
|
16.04.2009, 19:23 | #32 |
Moderator
|
ivas, спасибо! Значит, всё-таки, это нам не снится, а происходит наяву... угу...
Что ж, можно попробовать поразбираться дальше, померяться региональными и иными настройками. Пока же предлагаю (надеюсь, как временное решение) написанный по горячим следам статический метод для определения языка формул: X++: // Определение языка формул Excel для свойства Range.Formula // (именно Formula, а не FormulaLocal !!!) // подробности см. здесь: // [noparse]http://www.axforum.info/forums/showthread.php?p=195646#post195646[/noparse] // СПОСОБ: // помещаем в "международное" свойство формулу на русском языке // и проверяем последующую реакцию 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; } |
|
17.04.2009, 07:22 | #33 |
Axapta Retail User
|
|
|
24.06.2009, 16:34 | #34 |
Участник
|
Давно не заглядывал в этот топик, вот результат #NAME?
Офис 2003 сп3 английский Последний раз редактировалось Antoncheg; 24.06.2009 в 17:09. |
|
24.06.2009, 17:32 | #35 |
Moderator
|
соответственно, для этого вашего случая описанный выше метод excelFormulaLanguage вернет "English" и для range.Formula() надо будет использовать идентификатор функции "CONCATENATE" (а не "СЦЕПИТЬ").
Последний раз редактировалось Gustav; 25.06.2009 в 00:36. |
|
26.06.2009, 10:48 | #36 |
Участник
|
Проблемы со свойствами Formula и FormulaR1C1 - в способе их вызова из Ax
Все функции из Com-объектов вызываются не напрямую, а через специальный интерфейс IDispatch, в котором реализуется пара методов IDispatch::GetIdOfNames и IDispatch::Invoke. Первый метод по имени функции возвращает ее идентификатор (DispId), а второй - вызывает по этому идентификатору функцию выполнения. В обоих этих методах в качестве входного параметра присутствует языковый идентификатор - LCID. И Excel, как многоязыковая система, использует этот идентификатор для определения используемого языка. Т.е., если вызвать Formula() с параметром языка 0x0409 (en-Us), то функция внутри будет оперировать с передаваемыми данных, считая их англоязычными, если передать 0x0419 (ru), то, соответственно, русскоязычными. Dax при вызове подставляет константу LOCALE_USER_DEFAULT, что соответствует языку интерфейса по умолчанию, что для русского интерфейса Windows аналогично вызову Invoke() с параметром 0x0419 (ru) - отсюда и проблемы с интерпретацией буфера. Excel требует вводить имена функций на русском. В VBA при вызове подставляется другая константа LOCALE_NEUTRAL (0x0000). Эту константу Excel интерпретирует как код языка по умолчанию и требует вводить английские (точнее, американские) имена функций. Фактически, свойства Formula и FormulaR1C1 позволяют использовать любой язык, поддерживаемый Excel Свойства FormulaLocal и FormulaR1C1Local игнорируют передаваемый LCID и всегда используют LOCALE_USER_DEFAULT, что и приводит к одинаковым результатам при вызове из AX всех этих свойств Ну и в заключение, я набросал небольшую DLL, с помощью которой можно делать языконезависимый вызов свойств Formula и FormulaR1C1 из Ax X++: static void ExcelFormula(Args _args) { COM xlApp; COM wbk; COM rng; COMVariant cv; int iDispatch; DLL _DLL = new DLL("ComCall.dll"); //Получение DispId для свойства Formula DllFunction FormulaDispId = new DllFunction(_dll, "FormulaDispId"); //Получение DispId для свойства FormulaR1C1 DllFunction FormulaR1C1DispId = new DllFunction(_dll, "FormulaR1C1DispId"); //Установка свойства Formula для указанного объекта Range DllFunction SetFormula = new DllFunction(_dll, "Set_Formula"); //Получение свойства Formula для указанного объекта Range //первый вызов - для получения размера используемого буфера результата DllFunction GetFormulaLen = new DllFunction(_dll, "Get_Formula"); //второй вызов - для получения свойства DllFunction GetFormula = new DllFunction(_dll, "Get_Formula"); int dispId; int dispIdR1C1; Binary buf; int len; ComVariant var; ; FormulaDispId.returns(ExtTypes::DWord); FormulaDispId.arg(ExtTypes::DWord); FormulaR1C1DispId.returns(ExtTypes::DWord); FormulaR1C1DispId.arg(ExtTypes::DWord); SetFormula.returns(ExtTypes::DWord); SetFormula.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::String); //Для получения размера буфера GetFormulaLen.returns(ExtTypes::DWord); GetFormulaLen.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Dword); //Для получения результата буфера GetFormula.returns(ExtTypes::DWord); GetFormula.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Pointer); xlApp = new COM ('Excel.Application'); wbk = xlApp.Workbooks(); wbk = wbk.Add(); rng = xlApp.Range('A1'); iDispatch = rng.interface(); dispId = FormulaDispId.call(iDispatch); dispIdR1C1 = FormulaR1C1DispId.call(iDispatch); SetFormula.Call(iDispatch, dispId, '=sum(B1:D1)'); cv = rng.Text(); print cv.bStr(); len = GetFormulaLen.call(iDispatch, dispId, 0); buf = New Binary(len+1); GetFormula.call(iDispatch, dispId, buf); print "dll " + buf.string(0); len = GetFormulaLen.call(iDispatch, dispIdR1C1, 0); buf = New Binary(len+1); GetFormula.call(iDispatch, dispIdR1C1, buf); print "dll R1C1 " + buf.string(0); var = rng.formula(); print "Dax " + var.bStr(); rng = xlApp.Range('A2'); rng.Formula('=sum(B1:D1)'); cv = rng.Text(); print cv.bStr(); wbk.Close(False); // чтобы не оставался скрытый экземпляр Excel xlApp.Quit(); pause; }
__________________
Axapta v.3.0 sp5 kr2 |
|
|
За это сообщение автора поблагодарили: Wamr (5), tolstjak (1), ZVV (2), Antoncheg (1). |
30.06.2009, 13:14 | #37 |
Участник
|
Да, но если на разных машинах установлены разные версии офиса, становится проблематично...
|
|
01.07.2009, 16:24 | #38 |
Участник
|
Недавно стал разбираться с возможностью использования данного функционала при формировании отчетов в Эксел. Столкнулся с проблемой, которая для остальных возможно не является таковой.
Ее суть: static void aaa_TestADO_2(Args _args) { // ---------------------------------------------------------------------------- // ADODB.Recordset в оперативной памяти без привязки к источнику данных // ---------------------------------------------------------------------------- // EmplTable emplTable; InventTrans inventTrans; InventTable inventTable; PurchLine purchLine; InventDim inventDim; Voucher voucher; AccountNum account; TransDate date1; // TransDate toDate; // TransDate nDate, date1; ItemID itemID; str itemName; InventQTY qty; InventTransRefID zakaz; ItemGroupID itemGroupID; SysDim podraz; InventLocationID locationID; COM rstAxa; // ADO: Recordset COM flds, fld; // ADO: Fields, Field COM xlApp; // Excel.Application COM wbks, wbk; // Workbooks, Workbook COM wkss, wks; // Worksheets, Worksheet COM rng, cell, rngCR; // все Range COM font; // Range.Font COM entCol; // Range.EntireColumn COM actWin; // Excel.Application.ActiveWindow int i, iMax; // ============================================================================ // СНАЧАЛА ВЛОЖЕННАЯ ФУНКЦИЯ // ---------------------------------------------------------------------------- // функция для задания типа поля нашего Recordset-а в оперативной памяти // в данном демо-джобе используется для наглядности // для простоты используем всего 3 типа данных: число, строка и дата int adoTypeToExcel(str _type) { switch (_type) { // используются значения констант перечисления DateTypeEnum из топика TypeProperty (ADO) // (см. справку по ADO в файле ADO210.CHM - можно поискать на своем компе) case 'num' : return 5; // adDouble case 'str' : return 8; // adBSTR case 'date': return 133; // adDBDate case 'memo': return 203; // adLongVarChar } return 8; } // ============================================================================ // ТЕПЕРЬ ОСНОВНОЙ ПРОЦЕСС // Recordset создается в оперативной памяти - без Connection! rstAxa = new COM('ADODB.Recordset'); // формируем структуру нашего Recordset-а в "мозгах" flds = rstAxa.Fields(); flds.Append('Zakaz' , adoTypeToExcel('str' )); flds.Append('Voucher' , adoTypeToExcel('str' )); flds.Append('Цех' , adoTypeToExcel('str' )); flds.Append('НомГруппа', adoTypeToExcel('str' )); flds.Append('Номенклатура' , adoTypeToExcel('str' )); flds.Append('Наименование' , adoTypeToExcel('str' )); flds.Append('Склад' , adoTypeToExcel('str' )); // flds.Append('BirthDate' , adoTypeToExcel('date')); flds.Append('Кол-во' , adoTypeToExcel('num' )); flds.Append('Сумма' , adoTypeToExcel('num' )); // и наконец открываем его rstAxa.Open(); // ---------------------------------------------------------------------------- while select * from inventTrans // where ((inventTrans.DateFinancial >= fromDate && inventTrans.DateFinancial <= toDate) where ((inventTrans.DateFinancial >= 01\01\2009 && inventTrans.DateFinancial <= 31\05\2009) && inventTrans.TransType == 3) // && inventTrans.StatusReceipt == 1) join inventTable where (inventTrans.ItemId == inventTable.ItemId && inventTable.dataAreaId == "ssm") join purchLine where (inventTrans.ItemId == purchLine.ItemId && inventTrans.InventTransId == purchLine.InventTransId) join InventDim where (inventTrans.inventDimId == inventDim.inventDimId) { itemID = inventTrans.ItemId; itemName = inventTrans.itemName(); zakaz = inventTrans.TransRefId; qty = inventTrans.Qty; // amount0 = inventtrans.CostAmountPhysical; amount0 = inventTrans.CostAmountPosted; itemGroupID = inventTable.ItemGroupId; podraz = purchLine.Dimension[2]; voucher = inventTrans.Voucher; locationID = inventDim.InventLocationId; // бежим по таблице "......." Axapta // и добавляем записи (выбранные поля) в Recordset в оперативной памяти rstAxa.AddNew(); // fld = flds.Item('Zakaz' ); fld.Value(inventTrans.TransRefId ); // fld = flds.Item('Voucher' ); fld.Value(inventTrans.Voucher ); fld = flds.Item('Цех' ); fld.Value(purchLine.Dimension[2] ); fld = flds.Item('НомГруппа' ); fld.Value(inventTable.ItemGroupId); fld = flds.Item('Номенклатура' ); fld.Value(inventTrans.ItemId ); fld = flds.Item('Наименование' ); fld.Value(itemName); fld = flds.Item('Склад' ); fld.Value(inventDim.InventLocationId ); // fld = flds.Item('BirthDate' ); fld.Value(emplTable.BirthDate ); fld = flds.Item('Кол-во' ); fld.Value(inventTrans.Qty ); fld = flds.Item('Сумма' ); fld.Value(inventTrans.CostAmountPosted ); rstAxa.Update(); } // к этому моменту в оперативной памяти сформирована НАША таблица "Список сотрудников" // ---------------------------------------------------------------------------- // перед выгрузкой в Excel встанем на первую запись НАШЕЙ ТАБЛИЦЫ В ПАМЯТИ // и изменим имя сотрудника, дату его рождения и ID // НЕ БОЙТЕСЬ!!! Аксаптовская таблица EmplTable при этом НЕ ЗАТРАГИВАЕТСЯ!!! )) // rstAxa.MoveFirst(); // fld = flds.Item('Name' ); fld.Value('Самый молодой cотрудник с очень длинным именем'); // fld = flds.Item('BirthDate'); fld.Value(1\3\2006); // 1-е марта 2006 года // fld = flds.Item('EmplId' ); fld.Value('000333'); // потом обратите внимание, что в Excel ведущие нули у 000333 сохранятся! // rstAxa.Update(); // ---------------------------------------------------------------------------- // готовим новую рабочую книгу Excel для приема данных из Axapta: xlApp = new COM('Excel.Application'); xlApp.Visible(true); wbks = xlApp.Workbooks(); wbk = wbks.Add(); wkss = wbk.Worksheets(); wks = wkss.Item(1); wks.Name('AdoTestSheet'); rng = wks.Range('A1'); // ---------------------------------------------------------------------------- // выводим строку имен полей (1-я строка листа Excel) flds = rstAxa.Fields(); iMax = flds.Count() - 1; for (i = 0; i <= iMax; i += 1) { fld = flds.Item(i); cell = rng.Offset(0, i); cell.Value2(fld.Name()); } rngCR = rng.CurrentRegion(); font = rngCR.Font(); font.Bold(true); // делаем выведенные заголовки жирным шрифтом // ---------------------------------------------------------------------------- // выводим данные, начиная со 2-й строки листа Excel cell = rng.Offset(1, 0); cell.CopyFromRecordset(rstAxa); // ---------------------------------------------------------------------------- // подгоняем ширину столбцов Excel rngCR = rng.CurrentRegion(); entCol = rngCR.EntireColumn(); entCol.AutoFit(); // замораживаем строку заголовков Excel cell.Select(); actWin = xlApp.ActiveWindow(); actWin.FreezePanes(true); // ---------------------------------------------------------------------------- rstAxa.Close(); } С комментариями все работает, а если убрать комментарии со строк // fld = flds.Item('Zakaz' ); fld.Value(inventTrans.TransRefId ); // fld = flds.Item('Voucher' ); fld.Value(inventTrans.Voucher ); выдается ошибка: Вариантный тип, который используется методом СОМ - объекта, не поддерживается. В чем может быть засада?? Заранее благодарен. P.S. Ах 30 SP1 office 2003 SP3
__________________
Александр |
|
01.07.2009, 19:31 | #39 |
Участник
|
Цитата:
Сообщение от tolstjak
С комментариями все работает, а если убрать комментарии со строк
// fld = flds.Item('Zakaz' ); fld.Value(inventTrans.TransRefId ); // fld = flds.Item('Voucher' ); fld.Value(inventTrans.Voucher ); выдается ошибка: Вариантный тип, который используется методом СОМ - объекта, не поддерживается. В чем может быть засада?? Заранее благодарен. P.S. Ах 30 SP1 office 2003 SP3 Хотя, вообще-то, в COM-объекты крайне не желательно передавать данные "как есть" (за исключением целочисленных). Лучше "оборачивать" их в ComVariant. В данном случае примерно так: X++: ComVariant _comVariant; ; // и добавляем записи (выбранные поля) в Recordset в оперативной памяти rstAxa.AddNew(); fld = flds.Item('Zakaz' ); _comVariant = new ComVariant(); _comVariant.bStr(inventTrans.TransRefId); fld.Value(_comVariant); fld = flds.Item('Voucher' ); _comVariant.bStr(inventTrans.Voucher); fld.Value(_comVariant); |
|
|
За это сообщение автора поблагодарили: tolstjak (1). |
01.07.2009, 21:27 | #40 |
Участник
|
Цитата:
Сообщение от Владимир Максимов
Поля с правым выравниванием.
Хотя, вообще-то, в COM-объекты крайне не желательно передавать данные "как есть" (за исключением целочисленных). Лучше "оборачивать" их в ComVariant. В данном случае примерно так: X++: ComVariant _comVariant; ; // и добавляем записи (выбранные поля) в Recordset в оперативной памяти rstAxa.AddNew(); fld = flds.Item('Zakaz' ); _comVariant = new ComVariant(); _comVariant.bStr(inventTrans.TransRefId); fld.Value(_comVariant); fld = flds.Item('Voucher' ); _comVariant.bStr(inventTrans.Voucher); fld.Value(_comVariant);
__________________
Александр |
|