ExcelImporter.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using InABox.Core;
  5. using NPOI.SS.UserModel;
  6. namespace PRSDesktop
  7. {
  8. public class ExcelImporter<T> : BaseImporter<T> where T : Entity, IRemotable, IPersistent, new()
  9. {
  10. private readonly Dictionary<string, int> _columns = new();
  11. private IEnumerator _row;
  12. private ISheet _sheet = null;
  13. private IWorkbook _workbook;
  14. private DataFormatter formatter = new();
  15. public override bool Open(Stream stream)
  16. {
  17. var xls = WorkbookFactory.Create(stream);
  18. var sheet = xls.GetSheetAt(0);
  19. _row = sheet.GetRowEnumerator();
  20. _row.MoveNext();
  21. return true;
  22. }
  23. public override void Close()
  24. {
  25. if (_workbook != null)
  26. _workbook.Close();
  27. _workbook = null;
  28. }
  29. public override bool ReadHeader()
  30. {
  31. _columns.Clear();
  32. var fields = new List<string>();
  33. for (var i = 1; i < HeaderRow; i++)
  34. if (!MoveNext())
  35. return false;
  36. IEnumerator cells = ((IRow)_row.Current).GetEnumerator();
  37. while (cells.MoveNext())
  38. {
  39. var cell = (ICell)cells.Current;
  40. var value = cell.ToString();
  41. if (!string.IsNullOrWhiteSpace(value))
  42. {
  43. fields.Add(value);
  44. _columns[value] = cell.ColumnIndex;
  45. }
  46. Fields = fields.ToArray();
  47. }
  48. return true;
  49. }
  50. public override bool MoveNext()
  51. {
  52. return _row.MoveNext();
  53. }
  54. public override Dictionary<string, string> ReadLine()
  55. {
  56. var results = new Dictionary<string, string>();
  57. var row = _row.Current as IRow;
  58. foreach (var mapping in Mappings)
  59. {
  60. var field = mapping.Field;
  61. if (!string.IsNullOrWhiteSpace(field) && _columns.ContainsKey(field))
  62. {
  63. var cell = row.GetCell(_columns[field]);
  64. var value = "";
  65. if (cell != null)
  66. {
  67. var type = cell.CellType == CellType.Formula ? cell.CachedFormulaResultType : cell.CellType;
  68. if (type == CellType.Boolean)
  69. {
  70. value = cell.BooleanCellValue.ToString();
  71. }
  72. else if (type == CellType.Numeric)
  73. {
  74. if (DateUtil.IsCellDateFormatted(cell))
  75. value = cell.DateCellValue.ToString();
  76. else
  77. value = cell.NumericCellValue.ToString();
  78. }
  79. else if (type == CellType.String)
  80. {
  81. value = cell.StringCellValue;
  82. }
  83. else
  84. {
  85. value = cell.ToString();
  86. }
  87. }
  88. results[mapping.Property] = value;
  89. }
  90. else
  91. {
  92. results[mapping.Property] = mapping.Constant;
  93. }
  94. }
  95. return results;
  96. }
  97. }
  98. }
  99. /*
  100. //css_ref NPOI.dll
  101. //css_ref NPOI.OOXML.dll
  102. //css_ref NPOI.OpenXml4Net.dll
  103. using PRSDesktop;
  104. using Comal.Classes;
  105. using PRSDesktop.Utils;
  106. using InABox.Clients;
  107. using InABox.Configuration;
  108. using InABox.Core;
  109. using Syncfusion.UI.Xaml.Kanban;
  110. using Syncfusion.Windows.Controls.Grid;
  111. using System.Collections.Generic;
  112. using System.Collections.ObjectModel;
  113. using System.Runtime;
  114. using System.Diagnostics;
  115. using System.Linq;
  116. using System.Windows;
  117. using System.Windows.Controls;
  118. using System.Windows.Media;
  119. using System.Collections;
  120. using PRSDesktop.Forms.Export;
  121. using System.IO;
  122. using Ookii.Dialogs.Wpf;
  123. using NPOI.SS.UserModel;
  124. using System;
  125. using System.Reflection;
  126. using System.Linq.Expressions;
  127. using InABox.Reports;
  128. public class Module
  129. {
  130. public Object Data { get; set; }
  131. private int GetColumn(IRow row, String name)
  132. {
  133. IEnumerator cells = row.GetEnumerator();
  134. while (cells.MoveNext())
  135. {
  136. ICell cell = (ICell)cells.Current;
  137. if ((!String.IsNullOrWhiteSpace(cell.StringCellValue)) && (cell.StringCellValue.ToUpper().Trim().Equals(name.ToUpper().Trim())))
  138. return cell.ColumnIndex;
  139. }
  140. throw new Exception("Unable to find Column: " + name);
  141. }
  142. public String GetCellValue(ICell cell)
  143. {
  144. if (cell.CellType == NPOI.SS.UserModel.CellType.Formula)
  145. {
  146. if (cell.CachedFormulaResultType == NPOI.SS.UserModel.CellType.Numeric)
  147. return String.Format("{0:F}", cell.NumericCellValue.ToString());
  148. else
  149. return cell.StringCellValue;
  150. }
  151. return cell.ToString().Trim();
  152. }
  153. public void Set<T>(T item, Expression<Func<T>> property, object value, ref bool changed)
  154. {
  155. var member = (MemberExpression)property.Body;
  156. string propertyName = member.Member.Name;
  157. object val = CoreUtils.GetPropertyValue(item,propertyName);
  158. if ( ((val == null) && (value != null)) || (!val.Equals(value)) )
  159. {
  160. CoreUtils.SetPropertyValue(item,propertyName,value);
  161. changed = true;
  162. }
  163. }
  164. public void SetUserProperty<T>(T item, String userprop, object value, ref bool changed) where T : Entity
  165. {
  166. var userprops = item.UserProperties;
  167. object val = userprops.ContainsKey(userprop) ? userprops[userprop] : null;
  168. if ( ((val == null) && (value != null)) || (!val.Equals(value)) )
  169. {
  170. userprops[userprop] = value;
  171. changed = true;
  172. }
  173. }
  174. public bool Execute()
  175. {
  176. VistaOpenFileDialog dlg = new VistaOpenFileDialog();
  177. dlg.Filter = "Excel Files|*.xls; *.xlsx";
  178. if (dlg.ShowDialog() != true)
  179. return false;
  180. Progress.Show("Starting Up");
  181. Progress.SetMessage("Loading UOM Codes");
  182. List<ProductUOM> uoms = new Client<ProductUOM>().Load().ToList();
  183. Progress.SetMessage("Loading Groups");
  184. List<ProductGroup> groups = new Client<ProductGroup>().Load().ToList();
  185. Progress.SetMessage("Loading Products");
  186. List<Product> products = new Client<Product>().Load().ToList();
  187. Progress.SetMessage("Loading Suppliers");
  188. List<Supplier> suppliers = new Client<Supplier>().Load().ToList();
  189. Progress.SetMessage("Loading Supplier Products");
  190. List<SupplierProduct> supplierproducts = new Client<SupplierProduct>().Load().ToList();
  191. List<Guid> labels = new List<Guid>();
  192. Progress.SetMessage("Opening " + Path.GetFileName(dlg.FileName));
  193. List<String> Log = new List<string>();
  194. Log.Add(String.Format("Import Log {0:dd/MM/yyyy hh:mm:ss}",DateTime.Now));
  195. Log.Add("==============================");
  196. try
  197. {
  198. using (FileStream file = new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read))
  199. {
  200. IWorkbook xls = WorkbookFactory.Create(file);
  201. ISheet sheet = xls.GetSheet("Sheet1");
  202. IEnumerator rows = sheet.GetRowEnumerator();
  203. rows.MoveNext();
  204. IRow headerrow = (IRow)rows.Current;
  205. int ProductCodeColumn = GetColumn(headerrow,"Item Number");
  206. int ProductNameColumn = GetColumn(headerrow,"Item Description");
  207. int GroupColumn = GetColumn(headerrow, "Item Type");
  208. int UOMColumn = GetColumn(headerrow, "Base UOM");
  209. int SupplierColumn = GetColumn(headerrow, "Dflt Vendor");
  210. int CostColumn = GetColumn(headerrow, "Cost");
  211. List<String> Messages = new List<String>();
  212. int Row = 1;
  213. while ((rows.MoveNext()) && (Row <= 1)) //int.MaxValue))
  214. {
  215. Progress.SetMessage("Processing Row "+Row.ToString());
  216. Messages.Clear();
  217. Row++;
  218. IRow row = (IRow)rows.Current;
  219. try
  220. {
  221. Messages.Add("Getting Product Code");
  222. String productcode = row.GetCell(ProductCodeColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).StringCellValue.Trim();
  223. if (!String.IsNullOrWhiteSpace(productcode))
  224. {
  225. String productname = row.GetCell(ProductNameColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).StringCellValue.Trim();
  226. Messages.Add("Getting UOM");
  227. String uomcode = row.GetCell(UOMColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).StringCellValue.Trim();
  228. ProductUOM uom = null;
  229. if (!String.IsNullOrWhiteSpace(uomcode))
  230. {
  231. Messages.Add("UOM = ["+uomcode+"]");
  232. if (uoms == null)
  233. Messages.Add("UOM list is null");
  234. uom = uoms.FirstOrDefault(x=>x.Code.Equals(uomcode.ToUpper()));
  235. if (uom == null)
  236. {
  237. Messages.Add("Adding UOM");
  238. uom = new ProductUOM()
  239. {
  240. Code = uomcode.ToUpper(),
  241. Description = uomcode
  242. };
  243. new Client<ProductUOM>().Save(uom,"Imported from CCS");
  244. uoms.Add(uom);
  245. }
  246. }
  247. else
  248. uom = new ProductUOM();
  249. double UnitSize = 1.0;
  250. // If its an extrusion (ie uom = "L"), then strip out the length from the end of the code (if any)
  251. if (String.Equals(uomcode,"L") && productcode.Contains(" "))
  252. {
  253. String[] comps = productcode.Split(' ');
  254. productcode = String.Join(" ",comps.Reverse().Take(1).Reverse());
  255. String size = new string(comps.Last().Where(c => char.IsDigit(c) || char.Equals(c,'.')).ToArray());
  256. UnitSize = String.IsNullOrEmpty(size) ? 1.0 : double.Parse(size);
  257. }
  258. //What to do with the Unit Size Here?
  259. // Pro-Rata the cost?
  260. // Try to identify default length (compare to PRS)?
  261. // At this stage, we will just use it as the default unit size if a new product is to be created
  262. Messages.Add("Getting Group");
  263. String groupcode = row.GetCell(GroupColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).StringCellValue.Trim();
  264. ProductGroup group = null;
  265. if (!String.IsNullOrWhiteSpace(groupcode))
  266. {
  267. group = groups.FirstOrDefault(x=>x.Code.Equals(groupcode.ToUpper()));
  268. if (group == null)
  269. {
  270. Messages.Add("Adding Group");
  271. group = new ProductGroup()
  272. {
  273. Code = groupcode.ToUpper(),
  274. Description = groupcode
  275. };
  276. new Client<ProductGroup>().Save(group,"Imported from CCS");
  277. groups.Add(group);
  278. }
  279. }
  280. else
  281. group = new ProductGroup();
  282. Messages.Add("Locating Product");
  283. Product product = products.FirstOrDefault(x=>x.Code.Equals(productcode.ToUpper()));
  284. bool labelrequired = false;
  285. if (product == null)
  286. {
  287. Messages.Add("Adding Product");
  288. product = new Product()
  289. {
  290. Code = productcode.ToUpper()
  291. };
  292. product.UnitSize = UnitSize;
  293. products.Add(product);
  294. labelrequired = true;
  295. }
  296. product.Group.ID = group.ID;
  297. product.Units.ID = uom.ID;
  298. product.Name = productname;
  299. if (product.IsChanged())
  300. new Client<Product>().Save(product,"Imported from CCS");
  301. if (labelrequired)
  302. labels.Add(product.ID);
  303. Messages.Add("Getting Supplier");
  304. String suppliercode = row.GetCell(SupplierColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).StringCellValue.Trim();
  305. Supplier supplier = suppliers.FirstOrDefault(x=>x.Code.Equals(suppliercode.ToUpper()));
  306. if (supplier == null)
  307. {
  308. Messages.Add("Adding Supplier");
  309. supplier = new Supplier()
  310. {
  311. Code = suppliercode.ToUpper(),
  312. Name = suppliercode
  313. };
  314. new Client<Supplier>().Save(supplier,"Imported from CCS");
  315. suppliers.Add(supplier);
  316. }
  317. Messages.Add("Getting Supplier Cost");
  318. double suppliercost = row.GetCell(CostColumn, MissingCellPolicy.CREATE_NULL_AS_BLANK).NumericCellValue;
  319. SupplierProduct supprod = supplierproducts.FirstOrDefault(x=>x.ProductLink.ID.Equals(product.ID) && x.SupplierLink.ID.Equals(supplier.ID));
  320. if (supprod == null)
  321. {
  322. Messages.Add("Adding Supplier Product");
  323. supprod= new SupplierProduct();
  324. supprod.SupplierLink.ID = supplier.ID;
  325. supprod.ProductLink.ID = product.ID;
  326. supprod.TradePrice = suppliercost;
  327. supprod.Discount = 0.0F;
  328. supprod.CostPrice = suppliercost;
  329. supplierproducts.Add(supprod);
  330. }
  331. if (supprod.Discount != 100.0F)
  332. supprod.TradePrice = supprod.CostPrice * 100.0F / (100.0F / suppliercost);
  333. else
  334. {
  335. supprod.TradePrice = supprod.CostPrice;
  336. supprod.CostPrice = 0.0F;
  337. }
  338. if (supprod.IsChanged())
  339. new Client<SupplierProduct>().Save(supprod,"Imported from CCS");
  340. product.Supplier.ID = supprod.ID;
  341. product.ListPrice = supprod.TradePrice;
  342. product.Discount = supprod.Discount;
  343. product.NettPrice = supprod.CostPrice;
  344. if (product.IsChanged())
  345. new Client<Product>().Save(product,"Updated Default Supplier Cost");
  346. Messages.Add("Done");
  347. }
  348. }
  349. catch (Exception ei)
  350. {
  351. Messages.Add(String.Format("Row [{0}]: Exception: {1}", row.RowNum + 1, ei.Message));
  352. }
  353. Log.AddRange(Messages);
  354. }
  355. }
  356. Progress.Close();
  357. if (labels.Any())
  358. {
  359. ProductDataModel model = new ProductDataModel(new Filter<Product>(x=>x.ID).InList(labels.ToArray()));
  360. ReportTemplate template = new Client<ReportTemplate>().Load(new Filter<ReportTemplate>(x=>x.Section).IsEqualTo(model.Name).And(x=>x.Name).IsEqualTo("Product Barcode")).FirstOrDefault();
  361. if (template == null)
  362. {
  363. template = new ReportTemplate()
  364. {
  365. Section = model.Name,
  366. Name = "Product Barcode",
  367. Visible = true,
  368. SelectedRecords = true,
  369. AllRecords = false
  370. };
  371. new Client<ReportTemplate>().Save(template,"Autogenerated by CCS Import");
  372. }
  373. ReportUtils.PreviewReport(template,model,!Security.IsAllowed<CanDesignReports>() && !String.IsNullOrWhiteSpace(template.PrinterName), Security.IsAllowed<CanDesignReports>());
  374. }
  375. MessageBox.Show("Import Completed!");
  376. }
  377. catch (Exception e)
  378. {
  379. Log.Add(e.Message);
  380. Progress.Close();
  381. MessageBox.Show("Error while Importing File!\n\n" + e.Message);
  382. }
  383. Log.Add("");
  384. String LogFile = Path.ChangeExtension(dlg.FileName, ".txt");
  385. if (File.Exists(LogFile))
  386. Log.AddRange(File.ReadAllLines(LogFile));
  387. File.WriteAllLines(LogFile, Log.ToArray());
  388. Process.Start(LogFile);
  389. return true;
  390. }
  391. }
  392. */