![]() |
#1 |
Участник
|
Импорт информации по спланированным заказа на производство из экселя в АХ
Добрый день!
В виду извращенности бизнес логики необходимо импортировать data из Эксель и преобразовать ее в виде спланированных заказов на производство. В принципе ничего сложного. Формат таблицы импорта: Столбец1 Столбец2 Столбец3 Код номенклатуры Маршрут Колличество Вот джоб он это сделает: X++: static void _HTC_EXCELIMPORT_DataImportToAXFromExcel(Args _args) { SysExcelApplication xlsApplication; SysExcelWorkBooks xlsWorkBookCollection; SysExcelWorkBook xlsWorkBook; SysExcelWorksheets xlsWorkSheetCollection; SysExcelWorksheet xlsWorkSheet; SysExcelRange xlsRange; SysExcelCells Cells; SysExcelCell RCell; CommaIO inFile; int nRow,i; DialogField dialogPath; DialogField dlgFilepath; DialogField dlgReqPlanId; DialogField dlgRefType; DialogField dlgInventSiteId; Dialog dialog; Filename filename; ItemId ItemId; ItemGroupId ItemGroupId; ItemBomId ItemBomId; ItemRouteId itemRouteId; ReqPO ReqPo; ReqPlanId ReqPlanId; ReqRefType RefType; InventSiteId inventSiteId; ReqDate ReqDate; ReqDateOrder ReqDateOrder; Qty Qty; //FormStringControl FormStringControl = new FormStringControl(); ; dialog = new Dialog("Import"); dialogPath = dialog.addField(typeid(Filenameopen), "File Name"); dlgRefType = dialog.addField(typeid(ReqRefType), "Ref Type"); dlgReqPlanId = dialog.addField(typeid(ReqPlanId), "Plan Id"); dialog.run(); if (dialog.run()) { filename = (dialogPath.value()); ReqPlanId = dlgReqPlanId.value(); RefType = dlgRefType.value(); } inFile = new CommaIO (filename, 'R'); if (!inFile || infile.status() != IO_Status::Ok ) { throw error (strfmt("@SYS19312",filename)); } try { xlsApplication = SysExcelApplication::construct(); xlsWorkBookCollection = xlsApplication.workbooks(); xlsWorkBookCollection.open(filename); xlsWorkSheetCollection = xlsApplication.worksheets(); xlsWorkSheet = xlsWorkSheetCollection.itemFromNum(1); Cells = xlsWorkSheet.Cells(); nRow = 2; RCell = Cells.Item(nRow, 1); while(RCell.value().bStr() != "") { ItemId = RCell.value().bStr(); RCell = Cells.item(nRow,2); ItemRouteId = RCell.value().bStr(); RCell = Cells.item(nRow,3); Qty = RCell.value().double(); ReqDate = today(); ttsbegin; ReqPo.initValue(); ReqPo.ItemId = ItemId; ReqPo.ReqDate = ReqDate; ReqPo.ItemRouteId = ItemRouteId; ReqPo.ReqPlanId = ReqPlanId; ReqPo.ReqPOStatus = ReqPOStatus::Approved; ReqPo.RefType = RefType; ReqPO.Qty = Qty; ReqPo.CovInventDimId ="4799"; ReqPo.insert(); ttscommit; nRow++; RCell = Cells.Item(nRow, 1); } xlsApplication.quit(); xlsApplication.finalize(); info("Imported completed"); } catch( Exception::Error) { //Close Excel. xlsApplication.quit (); xlsApplication.finalize (); ttsabort; info("Unable to process the excel import "); } } И разумеется возник вопрос - А как это сделать?? Когда создается через форму то используется метод InventTable lookupBOMId одним из агрументов которого является FormStringControl. Но я планирую просто сделать класс для запуска импорта с точкой входа. |
|
![]() |
#2 |
Участник
|
InventTable.BomId()
|
|
![]() |
#3 |
Участник
|
Да спасибо. С этим я разобрался но вот проблема. Смотрите - спланированный заказ нормально занесся - на форме тоже отображаться, но калькуляция по спецификации и следовательно калькуляция того что нужно закупить - спланированных заказов на покупку не происходит. Не подскажите в чем дело?
X++: ttsbegin; ReqPO.ReqPlanId = ReqPlanId; ReqPO.RefType = ReqRefType::BOMPlannedOrder; ReqPO.initFromItemId(ItemId); ReqPO.Qty = Qty; ReqPo.BOMRouteCreated = ReqBOMRouteCreated::BOMRoute; Reqpo.CovInventDimId = InventDim::findOrCreate(inventDim).inventDimId; ReqPO.PurchUnit = inventTableModule::find(ItemId,moduleInventPurchSales::Invent).UnitId; ReqPo.ReqTime = timenow(); ReqPo.insert(); ReqTrans.initFromReqPo(ReqPo); ReqTrans.insert(); ttscommit; |
|
![]() |
#4 |
Banned
|
Потому как взорвать еще надо:
![]() ReqPlannedOrder::construct().insertFromForm() Цитата:
reqCalcExplodePo = this.getReqCalcExplode(reqTransPo);
reqCalcExplodePo.parmRecalculateBomLevels(_recalculateBomLevels); reqCalcExplodePo.run(); |
|
![]() |
#5 |
Участник
|
Итог! Будет все так::
X++: static void _HTC_EXCELIMPORT_DataImportToAXFromExcel(Args _args) { SysExcelApplication xlsApplication; SysExcelWorkBooks xlsWorkBookCollection; SysExcelWorkBook xlsWorkBook; SysExcelWorksheets xlsWorkSheetCollection; SysExcelWorksheet xlsWorkSheet; SysExcelRange xlsRange; SysExcelCells Cells; SysExcelCell RCell; CommaIO inFile; int nRow,i; DialogField dialogPath; DialogField dlgFilepath; DialogField dlgReqPlanId; DialogField dlgInventSiteId; Dialog dialog; Filename filename; ItemId ItemId; ItemGroupId ItemGroupId; ItemBomId ItemBomId; ItemRouteId itemRouteId; InventSiteId inventSiteId; ReqPO ReqPo; ReqTrans ReqTrans; ReqPlanId ReqPlanId; ReqCalcExplodePo reqCalcExplodePo; ReqDate ReqDate; ReqDateOrder ReqDateOrder; Qty Qty; InventDim InventDim; ; dialog = new Dialog("Import"); dialogPath = dialog.addField(typeid(Filenameopen), "File Name"); dlgReqPlanId = dialog.addField(typeid(ReqPlanId), "Plan Id"); dlgInventSiteId = dialog.addField(typeid(InventSiteId), "Site"); dialog.run(); if (dialog.run()) { filename = (dialogPath.value()); ReqPlanId = dlgReqPlanId.value(); InventSiteId = dlgInventSiteId.value(); } inFile = new CommaIO (filename, 'R'); if (!inFile || infile.status() != IO_Status::Ok ) { throw error (strfmt("@SYS19312",filename)); } try { xlsApplication = SysExcelApplication::construct(); xlsWorkBookCollection = xlsApplication.workbooks(); xlsWorkBookCollection.open(filename); xlsWorkSheetCollection = xlsApplication.worksheets(); xlsWorkSheet = xlsWorkSheetCollection.itemFromNum(1); Cells = xlsWorkSheet.Cells(); nRow = 2; RCell = Cells.Item(nRow, 1); InventDim.InventSiteId = InventSiteId; while(RCell.value().bStr() != "") { ItemId = RCell.value().bStr(); RCell = Cells.item(nRow,2); Qty = RCell.value().double(); ttsbegin; ReqPO.ReqPlanId = ReqPlanId; ReqPO.RefType = ReqRefType::BOMPlannedOrder; ReqPO.initFromItemId(ItemId); ReqPo.setBOMCreated(true); ReqPo.setRouteCreated(true); ReqPO.Qty = Qty; ReqPo.BOMRouteCreated = ReqBOMRouteCreated::BOMRoute; Reqpo.CovInventDimId = InventDim::findOrCreate(inventDim).inventDimId; ReqPO.PurchUnit = inventTableModule::find(ItemId,moduleInventPurchSales::Invent).UnitId; ReqPo.ReqTime = timenow(); ReqPo.ReqDateDlv = today(); ReqPo.ReqDateOrder = today(); ReqPo.insert(); ReqTrans.insertFromReqPo(ReqPo,True); ttscommit; reqCalcExplodePo = ReqCalcExplode::newReqTrans(ReqTrans, null); ReqCalcExplodePo.run(); nRow++; RCell = Cells.Item(nRow, 1); } xlsApplication.quit(); xlsApplication.finalize(); info("Imported completed"); } catch( Exception::Error) { //Close Excel. xlsApplication.quit (); xlsApplication.finalize (); ttsabort; info("Unable to process the excel import "); } } |
|
![]() |
#6 |
Участник
|
Class_DryRuImportPOFromExcel.xpo
Сделал на базе RunBaseBatch. |
|
|
За это сообщение автора поблагодарили: AlGol (1). |
![]() |
#7 |
Участник
|
Выявилась одна проблема: Дело в том что в экселе когда я хочу подгружать, код номенклатуры может иметь значение как 411509 - и это будет типа даннных string, так и 411509_1 а вот это почему то всегда число в экселе. Разумеется из за этого просходить сбой экспорта. Так как ожидалось получить стринг а получен был int. Может есть какой то способ проверить типа данных и в зависимости от этого выполнить преобразование или нет?
|
|
![]() |
#8 |
Участник
|
В общем то вроде как мне нужен метод который возвращает тип переменной. Должно же быть что то такое да?
|
|
![]() |
#9 |
Участник
|
Правильный ответ необходимо использовать функцию typeof() в методе run
typeof(RCell.value().bStr()) == Types::String ? RCell.value().bStr() : int2str(RCell.value().int()); Однако появился очень интересный баг. Когда я запускаю через класс - то есть щелкаю на класс то все подгружается нормально. Но я сделал кнопку и к ней прикрутил Menu item и назначил исполнение мой класс. И стала выпадать странная ошибка: Method 'value' in COM object of class 'Range' returned error code 0x80020005 (DISP_E_TYPEMISMATCH) which means: One or more of the arguments could not be coerced. Причины я не могу понять - если не сложно подскажите?? Когда запускаешь через класс - то все хорошо погружается. |
|
![]() |
#10 |
Banned
|
Классика. Зависит, кажется от места исполнения (клиента/сервера) и от того, есть ли ProgressBar и/или startLengthyOperation().
|
|
![]() |
#11 |
Участник
|
startLengthyOperation() использую, но все исполняю на сервере. Как то я не догоняю связь. Объясните пожалуйста.
|
|
![]() |
#12 |
Участник
|
startLengthyOperation() - убрал все работает. Исполняется на сервере. Не понимаю почему?
|
|
![]() |
#13 |
Banned
|
Когда вы выводите "песочные часы", Windows начинает как-то особенно чутко реагировать на длительные автономные процессы и считает, что AX или Excel "зависли". Как-то так.
|
|
![]() |
#14 |
Участник
|
Вот еще интересная штука. Смотрите: Загружаю данных из того же экселя в таблицу ForecastSales.
Все загружается но при этом при первом обновлении формы забавных глюк: За место одной записи 5 штук. Если форму закрыть и снова открыть то все нормально. Проект: __0150_HTC_DryRuImportForecastSalesExcel.xpo |
|