private void GatherChildrenID(MDataTable dt, string parentID, StringBuilder sb, string parentName = "ParentID") { if (!string.IsNullOrEmpty(parentID)) { List <MDataRow> rows = dt.FindAll(parentName + "='" + parentID + "'"); if (rows != null) { string id = string.Empty; foreach (MDataRow row in rows) { id = row.Get <string>(0); sb.Append("'" + id + "',"); GatherChildrenID(dt, id, sb, parentName); } } } }
/// <summary> /// 批量更新或插入。 /// </summary> /// <param name="dt"></param> /// <param name="excelRow"></param> /// <returns></returns> public static bool AcceptChanges(MDataTable dt, MDataRow excelRow, string objName = null) { if (excelRow == null) { MDataTable dtImportUnique = GridConfig.GetList(objName, GridConfig.SelectType.ImportUnique); string[] names = null; if (dtImportUnique != null && dtImportUnique.Rows.Count > 0) { names = new String[dtImportUnique.Rows.Count]; for (int i = 0; i < dtImportUnique.Rows.Count; i++) { names[i] = dtImportUnique.Rows[i].Get <string>("Field"); } } return(dt.AcceptChanges(AcceptOp.Auto, null, names)); } bool result = true; //获取相关配置 string[] tables = excelRow.Get <string>(Config_Excel.TableNames).Split(','); MDataTable configTable = GetExcelInfo(excelRow.Get <string>(Config_Excel.ExcelID)); Dictionary <string, string> rowPrimaryValue = new Dictionary <string, string>(); //存档每个表每行的主键值。 Dictionary <string, string> wherePrimaryValue = new Dictionary <string, string>(); //存档where条件对应的主键值。 using (MAction action = new MAction(tables[0])) { action.SetAopOff(); action.BeginTransation(); AppConfig.Debug.OpenDebugInfo = false; IExcelConfig excelConfigExtend = ExcelConfigFactory.GetExcelConfigExtend(); foreach (var table in tables) { GC.Collect();//后面的Fill查询代码循环上万次会增长太多内存,提前调用,能降低内存。 action.ResetTable(table); for (int i = 0; i < dt.Rows.Count; i++) { action.Data.Clear(); var row = dt.Rows[i]; foreach (var cell in row) //遍历所有数据行 { if (cell.Struct.TableName == table) //过滤出属于本表的字段。 { string[] items = cell.ColumnName.Split('.'); string columnName = items[items.Length - 1]; action.Set(columnName, cell.Value); } } #region 检测是否需要插入外键。 MDataTable foreignTable = configTable.FindAll("TableName='" + table + "' and IsForeignkey=1"); if (foreignTable != null) { foreach (var foreignRow in foreignTable.Rows) { string formatter = foreignRow.Get <string>("Formatter"); string fTableName = foreignRow.Get <string>("ForeignTable"); if (string.IsNullOrEmpty(formatter)) { //获取主键外值键 string key = fTableName + i; if (rowPrimaryValue.ContainsKey(key)) { string value = rowPrimaryValue[key]; action.Set(foreignRow.Get <string>("Field"), value); } } else // 从其它自定义列取值。 { MDataCell cell = row[formatter]; cell = cell ?? row[fTableName + "." + formatter]; if (cell != null) { action.Set(foreignRow.Get <string>("Field"), cell.Value); } } } foreignTable = null; } #endregion #region //获取唯一联合主键,检测是否重复 string where = string.Empty; List <MDataRow> rowList = configTable.FindAll("TableName='" + table + "' and IsUnique=1"); if (rowList != null && rowList.Count > 0) { bool IsUniqueOr = excelRow.Get <bool>("IsUniqueOr"); List <MDataCell> cells = new List <MDataCell>(); string errText = string.Empty; int errorCount = 0; foreach (var item in rowList) { var cell = action.Data[item.Get <string>(Config_ExcelInfo.Field)]; if (cell != null) { if (cell.IsNullOrEmpty) // 唯一主键是必填写字段 { errorCount++; errText += "[第" + (i + 1) + "行数据]:" + cell.Struct.ColumnName + "[" + cell.Struct.Description + "]不允许为空!\r\n"; } else { cells.Add(cell); } } } if (errorCount > 0) { if (!IsUniqueOr || errorCount == rowList.Count) { result = false; dt.DynamicData = new Exception(errText); goto err; } } MDataCell[] item2s = cells.ToArray(); where = action.GetWhere(!IsUniqueOr, item2s); item2s = null; rowList = null; } if (!string.IsNullOrEmpty(where)) { action.SetSelectColumns(action.Data.PrimaryCell.ColumnName); if (action.Fill(where))//根据条件查出主键ID { string key = table + where; if (wherePrimaryValue.ContainsKey(key)) { rowPrimaryValue.Add(table + i, wherePrimaryValue[key]);//记录上一个主键值。 } else { rowPrimaryValue.Add(table + i, action.Get <string>(action.Data.PrimaryCell.ColumnName));//记录上一个主键值。 } if (action.Data.GetState() == 2) { ExcelResult eResult = excelConfigExtend.BeforeUpdate(action.Data, row); if (eResult == ExcelResult.Ignore || (eResult == ExcelResult.Default && action.Update(where))) { continue;//已经存在了,更新,准备下一条。 } else { result = false; dt.DynamicData = new Exception("[第" + (i + 1) + "行数据]:" + action.DebugInfo); goto err; } } else { continue;//已经存在了,同时没有可更新字段 } } else if (!string.IsNullOrEmpty(action.DebugInfo))//产生错误信息,发生异常 { result = false; dt.DynamicData = new Exception("[第" + (i + 1) + "行数据]:" + action.DebugInfo); goto err; } } #endregion if (action.Data.GetState() == 0) { continue;//没有可映射插入的列。 } //插入前,调用函数(插入特殊主键等值) string errMsg; ExcelResult excelResult = excelConfigExtend.BeforeInsert(action.Data, row, out errMsg); if (excelResult == ExcelResult.Ignore) { continue; } if (excelResult == ExcelResult.Error || !action.Insert(InsertOp.ID)) { result = false; action.RollBack(); if (string.IsNullOrEmpty(errMsg)) { errMsg = "[第" + (i + 1) + "行数据]:" + action.DebugInfo; } dt.DynamicData = new Exception(errMsg); excelConfigExtend.OnInsertError(errMsg, dt); goto err; } //插入后事件(可以触发其它事件) excelConfigExtend.AfterInsert(action.Data, row, i == dt.Rows.Count - 1); string primaryKey = action.Get <string>(action.Data.PrimaryCell.ColumnName); rowPrimaryValue.Add(table + i, primaryKey);//记录上一个主键值。 if (!wherePrimaryValue.ContainsKey(table + where)) { wherePrimaryValue.Add(table + where, primaryKey); } } } err: action.EndTransation(); excelConfigExtend.Dispose(); } return(result); }
public static MemoryStream CreateExcelHeader(MDataTable header, Dictionary <string, string[]> validateData) { MemoryStream ms = new MemoryStream(); if (header != null && header.Rows.Count > 0) { MDataTable importHeader = header.FindAll("Import=1"); try { XSSFWorkbook export = new XSSFWorkbook(); ICellStyle style = GetStyle(export, HSSFColor.LightOrange.Index); ISheet sheet = export.CreateSheet("Sheet1");//创建内存Excel #region 创建引用 int rowStartIndex = 1; CreateValidationSheet(export, validateData, rowStartIndex); #endregion importHeader.Rows.Sort("ORDER BY MergeIndexed DESC");//Hidden=0 AND (Export=1 OR Field LIKE 'mg_%') MDataTable headTable = importHeader.Clone(); int ColTitleRowCount = 0; Dictionary <string, int> formatdic = new Dictionary <string, int>(); for (int i = importHeader.Rows.Count - 1; i >= 0; i--)//MDataTable 不支持 NOT LIKE { if (importHeader.Rows[i]["Field"].Value.ToString().IndexOf("mg") > -1) { importHeader.Rows.RemoveAt(i);//非字段列移除 } } int colSum = importHeader.Rows.Count;//实际列数 importHeader.Rows.Sort("ORDER BY OrderNum ASC"); if (!ExportMulHeader(header, true)) { IRow row = sheet.CreateRow(0); ICell cell; for (int i = 0; i < colSum; i++) { string title = importHeader.Rows[i]["Title"].Value.ToString(); cell = row.CreateCell(i); cell.SetCellValue(title);//设置列头 sheet.SetColumnWidth(i, 3000); cell.CellStyle = style; } } else { CreateMulHeadExcel(export, headTable, out ColTitleRowCount, colSum); ColTitleRowCount -= 1; } for (int i = 0; i < importHeader.Rows.Count; i++) { string formater = importHeader.Rows[i].Get <string>("Formatter"); if (!string.IsNullOrEmpty(formater) && formater.Length > 1 && !formatdic.ContainsKey(formater)) { formatdic.Add(formater, i);//存储列索引 } } int maxRow = 50000;//限制最大行数(07之前版本的excel最大行数为65536,但NOPI似乎没有支持到最大行数,这里设置为50000行,到60000行数据有效性失效) XSSFSheet xssfSheet = (XSSFSheet)sheet; XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(xssfSheet); for (int i = 0; i < importHeader.Rows.Count; i++) { MDataRow dtRow = importHeader.Rows[i]; string formatter = dtRow.Get <string>("Formatter"); if (formatter == "boolFormatter") { formatter = "#是否"; //对bool型特殊处理。 } if (!string.IsNullOrEmpty(formatter) && formatter.StartsWith("#") && validateData != null && formatter.Length > 1) //&& validateData.ContainsKey(formatter) { //处理数据的有效性 CellRangeAddressList regions = null; IDataValidationConstraint constraint = null; IDataValidation dataValidate = null; //int maxRow = 65535; if (validateData.ContainsKey(formatter)) { regions = new CellRangeAddressList(ColTitleRowCount + 1, maxRow, i, i); string key = formatter.Split('=')[0].Replace("#", "");// "V" + (char)formatter.Length;// formatter.Replace("#", "V"); /*03版本api * constraint = DVConstraint.CreateFormulaListConstraint(key);//);//validateData[formatter] * dataValidate = new HSSFDataValidation(regions, constraint); */ constraint = dvHelper.CreateFormulaListConstraint(key); dataValidate = dvHelper.CreateValidation(constraint, regions); sheet.AddValidationData(dataValidate); //regions = new CellRangeAddressList(ColTitleRowCount, maxRow, i, i); //string key = formatter.Split('=')[0].Replace("#", "");// "V" + (char)formatter.Length;// formatter.Replace("#", "V"); //constraint = DVConstraint.CreateFormulaListConstraint(key);//);//validateData[formatter] //dataValidate = new HSSFDataValidation(regions, constraint); //sheet.AddValidationData(dataValidate); } // if (formatter.StartsWith("#C"))//级联要接着父级后加数据有效性才行 { string Parentformatter = formatter; while (formatdic.ContainsKey(Parentformatter)) { int point = 0; int parentindex = formatdic[Parentformatter]; formatdic.Remove(Parentformatter); foreach (var item in formatdic) { if (item.Key.IndexOf('=') > -1) { string parent = item.Key.Split('=')[1]; parent = parent.Replace(">", "#"); if (parent.Equals(Parentformatter.Split('=')[0])) { int selfindex = item.Value; //int parentindex = formatdic[hereformatter]; string t = IntToMoreChar(parentindex); for (int im = ColTitleRowCount; im < maxRow; im++) { string func = string.Format("@INDIRECT({0}{1})", t, im + 1); regions = new CellRangeAddressList(im, im, selfindex, selfindex); constraint = dvHelper.CreateFormulaListConstraint(func); dataValidate = dvHelper.CreateValidation(constraint, regions); sheet.AddValidationData(dataValidate); } //for (int im = ColTitleRowCount; im < maxRow; im++)//1000应为maxRow //{ // string func = "INDIRECT(" + t + (im + 1) + ")";//excel2013不能级联,03可以,其他没测过 // regions = new CellRangeAddressList(ColTitleRowCount, im, selfindex, selfindex); // constraint = DVConstraint.CreateFormulaListConstraint(func); // dataValidate = new HSSFDataValidation(regions, constraint); // sheet.AddValidationData(dataValidate); //} Parentformatter = item.Key; break; } } point += 1; } if (point.Equals(formatdic.Count)) { Parentformatter = string.Empty; } } } } } export.Write(ms); ms.Flush(); ms.Close(); } catch (Exception err) { Log.WriteLogToTxt(err); } } return(ms); }