ExcelImport.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. using PTMedicalInsurance.Common;
  2. using PTMedicalInsurance.Helper;
  3. using Newtonsoft.Json.Linq;
  4. using PTMedicalInsurance.Variables;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Data;
  8. using System.Drawing;
  9. using System.Linq;
  10. using System.Threading;
  11. using System.Windows.Forms;
  12. using PTMedicalInsurance.Entity.Base;
  13. using Ganss.Excel;
  14. using PTMedicalInsurance.Entity;
  15. namespace PTMedicalInsurance.Forms
  16. {
  17. public partial class ExcelImport : Form
  18. {
  19. private string mapSection;
  20. private List<string> mapLst = new List<string>();
  21. private int buttonHeight = 30; // 按钮高度
  22. private int rowSpacing = 20; // 行间距
  23. private string excelFile = "";
  24. private Dictionary<string, KeyValuePair<string, string>> mappingPairs = new Dictionary<string, KeyValuePair<string,string>>();
  25. public delegate void ImportExcelHandler(string text);
  26. public event ImportExcelHandler onImport;
  27. public ExcelImport()
  28. {
  29. InitializeComponent();
  30. rdDrugs.CheckedChanged += checkChange;
  31. rdService.CheckedChanged += checkChange;
  32. rdMaterial.CheckedChanged += checkChange;
  33. }
  34. private void SourceLabel_MouseDown(object sender, MouseEventArgs e)
  35. {
  36. Button sourceLabel = (Button)sender;
  37. DoDragDrop(sourceLabel, DragDropEffects.Copy);
  38. }
  39. /// <summary>
  40. /// 画连接线
  41. /// </summary>
  42. /// <param name="sourceControl"></param>
  43. /// <param name="targetControl"></param>
  44. private void DrawLine(Control sourceControl, Control targetControl)
  45. {
  46. Graphics g = CreateGraphics();
  47. // 计算起始点和终点坐标(中心点)
  48. Point startPoint = new Point(sourceControl.Left + sourceControl.Width / 2,
  49. sourceControl.Top + sourceControl.Height / 2);
  50. Point endPoint = new Point(targetControl.Left + targetControl.Width / 2,
  51. targetControl.Top + targetControl.Height / 2);
  52. // 绘制连线(直线)
  53. Pen pen = new Pen(Color.Red); // 自定义颜色或样式
  54. g.DrawLine(pen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y);
  55. pen.Dispose();
  56. g.Dispose();
  57. }
  58. private void btnLoad_Click(object sender, EventArgs e)
  59. {
  60. if(openFileDlg.ShowDialog() == DialogResult.OK)
  61. {
  62. excelFile = openFileDlg.FileName;
  63. initMapper();
  64. }
  65. }
  66. private void readIni()
  67. {
  68. IniFile ini = new IniFile(Global.curEvt.path + @"\InsuMapRelation.ini");
  69. string excelImportSection = "";
  70. if (rdDrugs.Checked)
  71. {
  72. mapSection = "Drugs";
  73. excelImportSection = "ExcelImport_Drugs";
  74. }
  75. if (rdService.Checked)
  76. {
  77. mapSection = "Services";
  78. excelImportSection = "ExcelImport_Services";
  79. }
  80. if (rdMaterial.Checked)
  81. {
  82. mapSection = "Materials";
  83. excelImportSection = "ExcelImport_Materials";
  84. }
  85. mapLst = new List<string>();
  86. mapLst = ini.ReadKeys(mapSection);
  87. this.maxPreviewRows.Value = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "MaxPreviewRows")) ? int.Parse(ini.ReadValue(excelImportSection, "MaxPreviewRows")) : 20;
  88. this.maxUploadRows.Value = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "MaxRowNumber")) ? int.Parse(ini.ReadValue(excelImportSection, "MaxRowNumber")) : 5000;
  89. this.headerLineNum.Value = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "HeaderLineNum")) ? int.Parse(ini.ReadValue(excelImportSection, "HeaderLineNum")) : 1;
  90. this.headerStartNO.Value = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "HeaderStartNO")) ? int.Parse(ini.ReadValue(excelImportSection, "HeaderStartNO")) : 2;
  91. this.codeMinLength.Value = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "CodeMinLength")) ? int.Parse(ini.ReadValue(excelImportSection, "CodeMinLength")) : 6;
  92. this.txtCombinMark.Text = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "CombinMark")) ? ini.ReadValue(excelImportSection, "CombinMark") : "-";
  93. this.tbSheetName.Text = !string.IsNullOrEmpty(ini.ReadValue(excelImportSection, "SheetName")) ? ini.ReadValue(excelImportSection, "SheetName") : "总表";
  94. }
  95. private void initMapper()
  96. {
  97. mappingPairs.Clear();
  98. bool limited = true;
  99. if (maxPreviewRows.Value < 0) limited = false;
  100. ExcelMapper mapper = createMapper(limited);
  101. this.loadExcel(mapper,true);
  102. if (mapper == null || mapper.headers == null)
  103. {
  104. MessageBox.Show("mapper为空");
  105. return;
  106. }
  107. string[] igoreColumns = new string[]{ "HospitalDr","InterfaceDr","HisType","HisTypeName" };
  108. panelTarget.Controls.Clear();
  109. panelSource.Controls.Clear();
  110. mapper.headers.Where((x)=>!string.IsNullOrEmpty(x)).ToList<string>().ForEach((cellName) => {
  111. Button btn = AddButton(panelSource, cellName);
  112. btn.MouseDown += SourceLabel_MouseDown;
  113. });
  114. foreach (DataGridViewTextBoxColumn c in this.dataGridView1.Columns)
  115. {
  116. if (igoreColumns.Contains(c.DataPropertyName)) continue;
  117. Button btn = AddButton(panelTarget, c.HeaderText);
  118. btn.AllowDrop = true;
  119. btn.Tag = c.DataPropertyName;
  120. btn.DragDrop += panelTarget_DragDrop;
  121. btn.DragEnter += panelTarget_DragEnter;
  122. }
  123. }
  124. private ExcelMapper createMapper(bool limitedMaxRow)
  125. {
  126. try
  127. {
  128. ExcelMapper mapper = new ExcelMapper(excelFile);
  129. // 设置连接符
  130. mapper.CombinMark = txtCombinMark.Text.Trim();
  131. // 仅作为预览的数量
  132. if (limitedMaxRow)
  133. {
  134. mapper.MaxRowNumber = Decimal.ToInt32(maxPreviewRows.Value);
  135. }
  136. if (headerLineNum.Value < 1)
  137. {
  138. // 无标题
  139. mapper.HeaderRow = false;
  140. }
  141. else
  142. {
  143. mapper.HeaderRowNumber = int.Parse(headerLineNum.Value.ToString()) -1 ;
  144. mapper.MinRowNumber = int.Parse(headerStartNO.Value.ToString()) -1;
  145. }
  146. this.AddMapping(mapper);
  147. //new Thread(new ParameterizedThreadStart(loadExcel)).Start(mapper);
  148. return mapper;
  149. }catch(Exception e)
  150. {
  151. MessageBox.Show("createMapper:"+e.Message);
  152. }
  153. return null;
  154. }
  155. private int getHisType(out string typeName)
  156. {
  157. int type = 1;
  158. typeName = rdDrugs.Text;
  159. if (rdService.Checked)
  160. {
  161. type = 2;
  162. typeName = rdService.Text;
  163. }
  164. if (rdMaterial.Checked)
  165. {
  166. type = 3;
  167. typeName = rdMaterial.Text;
  168. }
  169. return type;
  170. }
  171. private List<MedInsuDirectory> loadExcel(object mapper,bool show)
  172. {
  173. List<MedInsuDirectory> list = new List<MedInsuDirectory>();
  174. try
  175. {
  176. string typeName;
  177. int type = getHisType(out typeName);
  178. if (mapper == null) return list;
  179. list = (mapper as ExcelMapper).Fetch<MedInsuDirectory>(tbSheetName.Text).ToList();
  180. //MessageBox.Show(list.Count.ToString());
  181. //if (mappingPairs.Count != 0)
  182. list.ForEach((mi) =>
  183. {
  184. mi.HospitalDr = (Global.inf.hospitalDr + "");
  185. mi.InterfaceDr = Global.inf.interfaceDr + "";
  186. mi.HisType = type.ToString();
  187. mi.HisTypeName = typeName;
  188. });
  189. // 过滤符合和code特征的数据
  190. int codeMinLen = int.Parse(codeMinLength.Value.ToString());
  191. MedInsuDirectory[] dataArray = list.Where((x) => x.Code == null || (x.Code != null && x.Code.Length > codeMinLen)).ToArray();
  192. //MedInsuDirectory[] dataArray = list.Where((x) => x.Code.Length > codeMinLen).ToArray();
  193. //MedInsuDirectory[] dArray = list.Where((x) => x.Code == null || (x.Code != null && x.Code.Length <= codeMinLen)).ToArray();
  194. //foreach (var x in dArray)
  195. //{
  196. // Global.writeLog(x.Code);
  197. //}
  198. if (show)
  199. {
  200. this.Invoke(new MethodInvoker(() =>
  201. {
  202. DataGridViewExtensions.Bind(this.dataGridView1, dataArray);
  203. }));
  204. }
  205. //btnLoad.Enabled = false;
  206. btnPreview.Enabled = true;
  207. }
  208. catch (Exception e)
  209. {
  210. MessageBox.Show(e.Message);
  211. }
  212. return list;
  213. }
  214. private Button AddButton(Panel containerPanel, string buttonText)
  215. {
  216. Button newButton = new Button();
  217. newButton.Name = containerPanel.Name + buttonText;
  218. newButton.Text = buttonText;
  219. newButton.Height = buttonHeight;
  220. newButton.AutoSize = true;
  221. int buttonCountInColumn = containerPanel.Controls.Count;
  222. // 设置按钮位置和大小
  223. newButton.Left = (containerPanel.Width - newButton.Width) / 2;
  224. if (buttonCountInColumn == 0)
  225. newButton.Top = rowSpacing / 2;
  226. else
  227. newButton.Top = containerPanel.Controls[buttonCountInColumn - 1].Bottom + rowSpacing;
  228. containerPanel.Controls.Add(newButton);
  229. return newButton;
  230. }
  231. private void panelTarget_DragEnter(object sender, DragEventArgs e)
  232. {
  233. if (e.Data.GetDataPresent(typeof(Button)))
  234. e.Effect = DragDropEffects.Copy;
  235. }
  236. private void panelTarget_DragDrop(object sender, DragEventArgs e)
  237. {
  238. Button target = (Button)sender;
  239. Button source = (Button)e.Data.GetData(typeof(Button));
  240. addMapping(source, target);
  241. }
  242. private void addMapping(Button source,Button target)
  243. {
  244. //string newKey = "[" + source.Text + "]==>[" + target.Text + "]";
  245. string newKey = source.Text + "=" + target.Text;
  246. // 记录excel列名和实体属性名的映射关系
  247. if (mappingPairs.ContainsKey(newKey)) return;
  248. mappingPairs.Add(newKey,new KeyValuePair<string, string>(source.Text, target.Text));
  249. source.BackColor = Color.Cyan;
  250. target.BackColor = Color.Cyan;
  251. lstMapping.Items.Add(newKey);
  252. }
  253. private void btnPreview_Click(object sender, EventArgs e)
  254. {
  255. Thread t = new Thread(() =>
  256. {
  257. ExcelMapper mapper = createMapper(maxPreviewRows.Value<0);
  258. this.loadExcel(mapper, true);
  259. });
  260. t.Start();
  261. btnComplete.Enabled = true;
  262. }
  263. private void AddMapping(ExcelMapper mapper)
  264. {
  265. foreach(string key in this.mappingPairs.Keys)
  266. {
  267. KeyValuePair<string, string> kv = this.mappingPairs[key];
  268. Type destType = typeof(MedInsuDirectory);
  269. string name = DataGridViewExtensions.getProperty<MedInsuDirectory>(kv.Value);
  270. if(!string.IsNullOrEmpty(name))
  271. {
  272. mapper.AddMapping(destType, kv.Key, name);
  273. }
  274. }
  275. }
  276. private void btnComplete_Click(object sender, EventArgs e)
  277. {
  278. string tips = string.Format("医院【{0}】,接口【{1}】 \r\n 你确定要导入这些数据吗?", Global.inf.hospitalDr, Global.inf.interfaceDr);
  279. if (!tools.Confirm(tips)) return;
  280. new Thread(new ThreadStart(upload)).Start();
  281. }
  282. private void upload()
  283. {
  284. ExcelMapper excel = createMapper(false);
  285. List<MedInsuDirectory> list = this.loadExcel(excel,false);
  286. // 每次最大条数
  287. int pageSize = Decimal.ToInt32(maxUploadRows.Value);
  288. int index = 0;
  289. int pages = list.Count / pageSize;
  290. if ((list.Count % pageSize) > 0)
  291. {
  292. pages = pages + 1;
  293. }
  294. while (index < pages)
  295. {
  296. int count = pageSize;
  297. if((index+1) * pageSize > list.Count) count = list.Count % pageSize;
  298. List<MedInsuDirectory> pageList = list.GetRange(index * pageSize, count);
  299. // upload to server
  300. uploadToServer(pageList);
  301. index++;
  302. }
  303. MessageBox.Show("目录上传完成!");
  304. }
  305. private void uploadToServer(List<MedInsuDirectory> list)
  306. {
  307. InvokeHelper helper = new InvokeHelper();
  308. string data = getUploadParams(list);
  309. if (this.onImport != null)
  310. {
  311. this.onImport.Invoke("开始上传:"+data);
  312. }
  313. JObject ret = helper.invokeInsuService(data, "医保目录上传");
  314. if (this.onImport != null)
  315. {
  316. this.onImport.Invoke("返回:"+JsonHelper.toJsonString(ret));
  317. }
  318. }
  319. private string getUploadParams(List<MedInsuDirectory> list)
  320. {
  321. //再过滤一次
  322. int codeMinLen = int.Parse(codeMinLength.Value.ToString());
  323. MedInsuDirectory[] dataArray = list.Where((x) => (x.Name?.Length>2) && (x.Code?.Length > codeMinLen)).ToArray();
  324. Request request = new Request();
  325. request.code = "02020145";
  326. request.data = list.ToArray();
  327. request.session = new object[] { LoginUser.Current.user };
  328. return JsonHelper.toJsonString(request);
  329. }
  330. private void ExcelImport_Load(object sender, EventArgs e)
  331. {
  332. this.rdDrugs.Checked = true;
  333. this.btnComplete.Enabled = false;
  334. this.btnPreview.Enabled = false;
  335. readIni();
  336. }
  337. private void btnMapping_Click(object sender, EventArgs e)
  338. {
  339. foreach (Control c in panelSource.Controls)
  340. {
  341. Control[] targets = panelTarget.Controls.Find(panelTarget.Name + c.Text, true);
  342. if (targets != null && targets.Length == 1)
  343. {
  344. addMapping((Button)c, (Button)targets[0]);
  345. }
  346. }
  347. }
  348. private void lstMapping_DoubleClick(object sender, EventArgs e)
  349. {
  350. if (lstMapping.SelectedIndex != -1)
  351. {
  352. string key = lstMapping.Items[lstMapping.SelectedIndex].ToString();
  353. lstMapping.Items.Remove(key);
  354. this.mappingPairs.Remove(key);
  355. }
  356. }
  357. private void button2_Click(object sender, EventArgs e)
  358. {
  359. if (lstMapping.Items.Count == 0)
  360. {
  361. MessageBox.Show("映射关系不能为空");
  362. return;
  363. }
  364. IniFile ini = new IniFile(Global.curEvt.path+ @"\InsuMapRelation.ini");
  365. ini.DeleteSection(mapSection);
  366. foreach (var item in lstMapping.Items)
  367. {
  368. string pair = item.ToString();
  369. int length = pair.Length;
  370. int pos = pair.IndexOf("=");
  371. ini.WriteValue(mapSection, pair.Substring(0, pos), pair.Substring(pos+1, length - pos - 1));
  372. }
  373. }
  374. private void button1_Click(object sender, EventArgs e)
  375. {
  376. initMapper();
  377. lstMapping.Items.Clear();
  378. IniFile ini = new IniFile(Global.curEvt.path + @"\InsuMapRelation.ini");
  379. foreach (var item in mapLst)
  380. {
  381. string sourceField = item.ToString();
  382. string targetField = ini.ReadValue(mapSection, item.ToString());
  383. string newKey = sourceField + "=" + targetField;
  384. lstMapping.Items.Add(newKey);
  385. mappingPairs.Add(newKey, new KeyValuePair<string, string>(sourceField ,targetField));
  386. Control[] targets = panelTarget.Controls.Find(panelTarget.Name + targetField, true);
  387. Control[] sources = panelSource.Controls.Find(panelSource.Name + sourceField, true);
  388. //MessageBox.Show(sourceField);
  389. //foreach (Control ite in targets)
  390. //{
  391. // MessageBox.Show(((Button)ite).Name);
  392. //}
  393. //foreach (Control ite in panelTarget.Controls)
  394. //{
  395. // MessageBox.Show(((Button)ite).Name);
  396. //}
  397. if (targets != null && targets.Length == 1)
  398. {
  399. ((Button)targets[0]).BackColor = Color.Cyan;
  400. }
  401. if (sources != null && sources.Length == 1)
  402. {
  403. ((Button)sources[0]).BackColor = Color.Cyan;
  404. }
  405. }
  406. }
  407. private void checkChange(object sender, EventArgs e)
  408. {
  409. readIni();
  410. }
  411. }
  412. }