public static bool ExportToExcel(string tableName) { Excel.Application application = new Excel.Application(); // 不显示Excel窗口 application.Visible = false; // 不显示警告对话框 application.DisplayAlerts = false; // 禁止屏幕刷新 application.ScreenUpdating = false; // 编辑非空单元格时不进行警告提示 application.AlertBeforeOverwriting = false; string savePath = System.IO.Path.GetFullPath(Utils.CombinePath(AppValues.ExportExcelPath, tableName + ".xlsx")); // 检查要导出的Excel文件是否已存在且正被其他程序使用 if (Utils.GetFileState(savePath) == FileState.IsOpen) { Utils.LogErrorAndExit("错误:导出目标路径存在该Excel文件且该文件正被其他程序打开,请关闭后重试"); return(false); } // 新建Excel工作簿 Excel.Workbook workbook = application.Workbooks.Add(); // 在名为data的Sheet表中填充数据 Excel.Worksheet dataWorksheet = workbook.Sheets[1] as Excel.Worksheet; dataWorksheet.Name = AppValues.EXCEL_DATA_SHEET_NAME; // 设置标签按钮的颜色 if (AppValues.DataSheetTabColorIndex > 0) { dataWorksheet.Tab.ColorIndex = (XlColorIndex)AppValues.DataSheetTabColorIndex; } // 设置表格中所有单元格均为文本格式,避免很大的数字写入Excel时被转为科学计数法形式,使得XlsxToLua工具无法正确读取数值(注意必须在写入数据前就设置,否则会导致写入Excel的日期字符串最终变成数字) dataWorksheet.Cells.NumberFormatLocal = "@"; System.Data.DataTable data = MySQLOperateHelper.ReadDatabaseTable(tableName); System.Data.DataTable columnInfo = MySQLOperateHelper.GetColumnInfo(tableName); string tableComment = MySQLOperateHelper.GetDatabaseTableComment(tableName); int dataColumnCount = columnInfo.Rows.Count; // 按XlsxToLua工具规定的格式导出配置参数及数据 // 注意Excel中左上角单元格下标为[1,1],而DataTable中为[0,0] for (int columnIndex = 1; columnIndex <= dataColumnCount; ++columnIndex) { // 第一行为字段描述 string desc = columnInfo.Rows[columnIndex - 1]["COLUMN_COMMENT"].ToString(); dataWorksheet.Cells[AppValues.DATA_FIELD_DESC_INDEX, columnIndex] = desc; // 第二行为字段变量名 string fileName = columnInfo.Rows[columnIndex - 1]["COLUMN_NAME"].ToString(); dataWorksheet.Cells[AppValues.DATA_FIELD_NAME_INDEX, columnIndex] = fileName; // 第三行为字段数据类型 string databaseDataType = columnInfo.Rows[columnIndex - 1]["DATA_TYPE"].ToString(); string fullDatabaseDataType = columnInfo.Rows[columnIndex - 1]["COLUMN_TYPE"].ToString(); // 取出数据类型完整定义的括号中声明的长度 string length = null; int leftBracketIndex = fullDatabaseDataType.LastIndexOf("("); int rightBracketIndex = fullDatabaseDataType.LastIndexOf(")"); if (leftBracketIndex != -1 && rightBracketIndex > leftBracketIndex) { length = fullDatabaseDataType.Substring(leftBracketIndex + 1, rightBracketIndex - leftBracketIndex - 1); } string dataType = _ConvertDataType(databaseDataType, length); if (string.IsNullOrEmpty(dataType)) { Utils.LogErrorAndExit(string.Format("错误:数据表中名为{0}的列数据类型为{1},而_ConvertDataType函数中未定义该数据库数据类型对应XlsxToLua工具要求的数据类型,请补全转换关系后重试", fileName, fullDatabaseDataType)); return(false); } else { dataWorksheet.Cells[AppValues.DATA_FIELD_DATA_TYPE_INDEX, columnIndex] = dataType; } // 第四行为字段检查规则 string checkRule = _GetCheckRuleByDatabaseColumnInfo(columnInfo.Rows[columnIndex - 1], dataType); dataWorksheet.Cells[AppValues.DATA_FIELD_CHECK_RULE_INDEX, columnIndex] = checkRule; // 第五行为导出到数据库中的字段名及类型 dataWorksheet.Cells[AppValues.DATA_FIELD_EXPORT_DATABASE_FIELD_INFO, columnIndex] = string.Format("{0}({1})", fileName, fullDatabaseDataType.ToUpper()); // 从第六行开始导入数据库中数据表所填写的数据 int dataCount = data.Rows.Count; for (int i = 0; i < dataCount; ++i) { dataWorksheet.Cells[AppValues.DATA_FIELD_DATA_START_INDEX + i, columnIndex] = data.Rows[i][columnIndex - 1].ToString(); } // 将每列的背景色按配置进行设置 if (AppValues.ColumnBackgroundColorIndex != null) { int colorIndex = AppValues.ColumnBackgroundColorIndex[(columnIndex - 1) % AppValues.ColumnBackgroundColorIndex.Count]; if (colorIndex > 0) { dataWorksheet.get_Range(Utils.GetExcelColumnName(columnIndex) + "1").EntireColumn.Interior.ColorIndex = colorIndex; } } } // 为了美化生成的Excel文件,设置单元格自动列宽(使得列宽根据内容自动调整,每个单元格在一行中可显示完整内容)。然后对于因内容过多而通过自动列宽后超过配置文件中配置的最大列宽的单元格,强制缩小列宽到所允许的最大宽度。最后设置单元格内容自动换行,使得单元格自动扩大高度以显示所有内容 // 注意以下操作需在插入完所有数据后进行,否则插入数据前设置自动列宽无效 if (AppValues.ExcelColumnMaxWidth > 0) { // 设置表格中所有单元格均自动列宽 dataWorksheet.Columns.AutoFit(); // 对于因内容过多而通过自动列宽后超过配置文件中配置的最大列宽的单元格,强制缩小列宽到所允许的最大宽度 for (int columnIndex = 1; columnIndex <= dataColumnCount; ++columnIndex) { double columnWidth = Convert.ToDouble(dataWorksheet.get_Range(Utils.GetExcelColumnName(columnIndex) + "1").EntireColumn.ColumnWidth); if (columnWidth > AppValues.ExcelColumnMaxWidth) { dataWorksheet.get_Range(Utils.GetExcelColumnName(columnIndex) + "1").EntireColumn.ColumnWidth = AppValues.ExcelColumnMaxWidth; } } // 设置表格中所有单元格均自动换行 dataWorksheet.Cells.WrapText = true; } // 对前五行配置列执行窗口冻结 Excel.Range excelRange = dataWorksheet.get_Range(dataWorksheet.Cells[AppValues.DATA_FIELD_DATA_START_INDEX, 1], dataWorksheet.Cells[AppValues.DATA_FIELD_DATA_START_INDEX, 1]); excelRange.Select(); application.ActiveWindow.FreezePanes = true; // 先对整表设置虚线边框 dataWorksheet.Cells.Borders[XlBordersIndex.xlEdgeLeft].Weight = XlBorderWeight.xlHairline; dataWorksheet.Cells.Borders[XlBordersIndex.xlEdgeRight].Weight = XlBorderWeight.xlHairline; dataWorksheet.Cells.Borders[XlBordersIndex.xlEdgeTop].Weight = XlBorderWeight.xlHairline; dataWorksheet.Cells.Borders[XlBordersIndex.xlEdgeBottom].Weight = XlBorderWeight.xlHairline; dataWorksheet.Cells.Borders[XlBordersIndex.xlInsideHorizontal].Weight = XlBorderWeight.xlHairline; dataWorksheet.Cells.Borders[XlBordersIndex.xlInsideVertical].Weight = XlBorderWeight.xlHairline; // 再对前五行配置列添加内外实线边框 excelRange = dataWorksheet.get_Range(dataWorksheet.Cells[AppValues.DATA_FIELD_DESC_INDEX, 1], dataWorksheet.Cells[AppValues.DATA_FIELD_EXPORT_DATABASE_FIELD_INFO, dataColumnCount]); excelRange.Borders[XlBordersIndex.xlEdgeLeft].Weight = XlBorderWeight.xlThin; excelRange.Borders[XlBordersIndex.xlEdgeRight].Weight = XlBorderWeight.xlThin; excelRange.Borders[XlBordersIndex.xlEdgeTop].Weight = XlBorderWeight.xlThin; excelRange.Borders[XlBordersIndex.xlEdgeBottom].Weight = XlBorderWeight.xlThin; excelRange.Borders[XlBordersIndex.xlInsideHorizontal].Weight = XlBorderWeight.xlThin; excelRange.Borders[XlBordersIndex.xlInsideVertical].Weight = XlBorderWeight.xlThin; dataWorksheet.SaveAs(savePath); workbook.SaveAs(savePath); // 新建名为config的Sheet表 Excel.Worksheet configWorksheet = workbook.Sheets.Add(Type.Missing, dataWorksheet) as Excel.Worksheet; configWorksheet.Name = AppValues.EXCEL_CONFIG_SHEET_NAME; // 设置标签按钮的颜色 if (AppValues.ConfigSheetTabColorIndex > 0) { configWorksheet.Tab.ColorIndex = (XlColorIndex)AppValues.ConfigSheetTabColorIndex; } // 设置表格中所有单元格均为文本格式 configWorksheet.Cells.NumberFormatLocal = "@"; // 写入导出到数据库中的字段名及类型配置 configWorksheet.Cells[1, 1] = AppValues.CONFIG_NAME_EXPORT_DATABASE_TABLE_NAME; configWorksheet.Cells[2, 1] = tableName; // 写入导出到数据库中表格的Comment configWorksheet.Cells[1, 2] = AppValues.CONFIG_NAME_EXPORT_DATABASE_TABLE_COMMENT; configWorksheet.Cells[2, 2] = tableComment; // 设置表格中所有单元格均自动换行 configWorksheet.Cells.WrapText = true; // 设置列背景色 if (AppValues.ColumnBackgroundColorIndex != null) { int configColumnCount = configWorksheet.UsedRange.Columns.Count; for (int columnIndex = 1; columnIndex <= configColumnCount; ++columnIndex) { int colorIndex = AppValues.ColumnBackgroundColorIndex[(columnIndex - 1) % AppValues.ColumnBackgroundColorIndex.Count]; if (colorIndex > 0) { configWorksheet.get_Range(Utils.GetExcelColumnName(columnIndex) + "1").EntireColumn.Interior.ColorIndex = colorIndex; } } } // 对第一行配置名行执行窗口冻结 excelRange = configWorksheet.get_Range("A2"); excelRange.Select(); application.ActiveWindow.FreezePanes = true; configWorksheet.SaveAs(savePath); // 设置默认显示的Sheet为data表 dataWorksheet.Select(); workbook.SaveAs(savePath); workbook.Close(false); application.Workbooks.Close(); application.Quit(); //System.Runtime.InteropServices.Marshal.ReleaseComObject(application); _KillExcelProcess(application, tableName); return(true); }
static void Main(string[] args) { // 读取本工具所在路径下的config配置文件 string errorString = null; string configFilePath = Utils.CombinePath(AppValues.PROGRAM_FOLDER_PATH, AppValues.CONFIG_FILE_NAME); AppValues.ConfigData = TxtConfigReader.ParseTxtConfigFile(configFilePath, ":", out errorString); if (!string.IsNullOrEmpty(errorString)) { Utils.LogErrorAndExit(errorString); } // 检查填写的Excel导出目录是否存在 if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_EXPORT_EXCEL_PATH)) { AppValues.ExportExcelPath = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_EXPORT_EXCEL_PATH].Trim(); if (!Directory.Exists(AppValues.ExportExcelPath)) { Utils.LogErrorAndExit(string.Format("config配置文件中声明的导出Excel文件的存放目录不存在,你填写的为\"{0}\"", AppValues.ExportExcelPath)); } } else { Utils.LogErrorAndExit(string.Format("未在config配置文件中以名为\"{0}\"的key声明导出Excel文件的存放目录", AppValues.APP_CONFIG_KEY_EXPORT_EXCEL_PATH)); } // 获取设置的Excel文件中列的最大宽度 if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_EXCEL_COLUMN_MAX_WIDTH)) { double inputExcelColumnMaxWidth = -1; string inputParam = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_EXCEL_COLUMN_MAX_WIDTH]; if (double.TryParse(inputParam, out inputExcelColumnMaxWidth) == true) { if (inputExcelColumnMaxWidth > 0) { AppValues.ExcelColumnMaxWidth = inputExcelColumnMaxWidth; } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的Excel文件中列的最大宽度非法,必须大于0,你输入的为\"{0}\"", inputParam)); } } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的Excel文件中列的最大宽度不是一个合法数字,你输入的为\"{0}\"", inputParam)); } } else { Utils.LogWarning(string.Format("警告:未在config配置文件中以名为\"{0}\"的key声明生成的Excel文件中列的最大宽度,本工具将不对生成的Excel文件进行美化", AppValues.APP_CONFIG_KEY_EXCEL_COLUMN_MAX_WIDTH)); } const int COLOR_INDEX_MIN = 0; const int COLOR_INDEX_MAX = 56; // 获取设置的每列背景色,如果进行了设置需检查ColorIndex是否正确 if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_COLUMN_BACKGROUND_COLOR)) { AppValues.ColumnBackgroundColorIndex = new List <int>(); string inputParam = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_COLUMN_BACKGROUND_COLOR]; string[] colorIndexString = inputParam.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (colorIndexString.Length > 0) { foreach (string oneColorIndexString in colorIndexString) { int oneColorIndex = -1; if (int.TryParse(oneColorIndexString, out oneColorIndex) == true) { if (oneColorIndex >= COLOR_INDEX_MIN && oneColorIndex <= COLOR_INDEX_MAX) { AppValues.ColumnBackgroundColorIndex.Add(oneColorIndex); } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的颜色索引值\"{0}\"非法,必须介于{1}到{2}之间", oneColorIndex, COLOR_INDEX_MIN, COLOR_INDEX_MAX)); } } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的颜色索引值\"{0}\"不是一个合法数字", oneColorIndexString)); } } } else { Utils.LogErrorAndExit(string.Format("config配置文件中以名为\"{0}\"的key声明各列背景色不允许为空", AppValues.APP_CONFIG_KEY_COLUMN_BACKGROUND_COLOR)); } } // 获取设置的data、config两张Sheet表的标签按钮颜色 if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_DATA_SHEET_TAB_COLOR)) { string colorIndexString = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_DATA_SHEET_TAB_COLOR]; int colorIndex = -1; if (int.TryParse(colorIndexString, out colorIndex) == true) { if (colorIndex >= COLOR_INDEX_MIN && colorIndex <= COLOR_INDEX_MAX) { AppValues.DataSheetTabColorIndex = colorIndex; } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的data表标签按钮颜色索引值\"{0}\"非法,必须介于{1}到{2}之间", colorIndex, COLOR_INDEX_MIN, COLOR_INDEX_MAX)); } } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的data表标签按钮颜色索引值\"{0}\"不是一个合法数字", colorIndexString)); } } if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_CONFIG_SHEET_TAB_COLOR)) { string colorIndexString = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_CONFIG_SHEET_TAB_COLOR]; int colorIndex = -1; if (int.TryParse(colorIndexString, out colorIndex) == true) { if (colorIndex >= COLOR_INDEX_MIN && colorIndex <= COLOR_INDEX_MAX) { AppValues.ConfigSheetTabColorIndex = colorIndex; } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的config表标签按钮颜色索引值\"{0}\"非法,必须介于{1}到{2}之间", colorIndex, COLOR_INDEX_MIN, COLOR_INDEX_MAX)); } } else { Utils.LogErrorAndExit(string.Format("config配置文件中声明的config表标签按钮颜色索引值\"{0}\"不是一个合法数字", colorIndexString)); } } // 获取要导出的数据表名 List <string> exportTableName = new List <string>(); // 在这里自定义获取要导出的数据表名的方法(这里以在config.txt中进行配置为例,还可以采用类似表名特殊前缀标识等方式实现) if (AppValues.ConfigData.ContainsKey(AppValues.APP_CONFIG_KEY_EXPORT_DATA_TABLE_NAMES)) { string exportTableNameString = AppValues.ConfigData[AppValues.APP_CONFIG_KEY_EXPORT_DATA_TABLE_NAMES].Trim(); if (string.IsNullOrEmpty(exportTableNameString)) { Utils.LogErrorAndExit(string.Format("config配置文件中以名为\"{0}\"的key声明要导出的数据表名不允许为空", AppValues.APP_CONFIG_KEY_EXPORT_DATA_TABLE_NAMES)); } else { string[] tableNames = exportTableNameString.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries); foreach (string tableName in tableNames) { exportTableName.Add(tableName.Trim()); } } } else { Utils.LogErrorAndExit(string.Format("未在config配置文件中以名为\"{0}\"的key声明要导出的数据表名", AppValues.APP_CONFIG_KEY_EXPORT_DATA_TABLE_NAMES)); } // 连接MySQL数据库 MySQLOperateHelper.ConnectToDatabase(out errorString); if (!string.IsNullOrEmpty(errorString)) { Utils.LogErrorAndExit(string.Format("无法连接到MySQL数据库,{0}", errorString)); } // 检查声明的要导出的数据库表格是否存在,若存在导出到Excel foreach (string tableName in exportTableName) { if (MySQLOperateHelper.ExistTableNames.Contains(tableName)) { Utils.Log(string.Format("导出数据表{0}:", tableName)); ExcelOperateHelper.ExportToExcel(tableName); Utils.Log("成功"); } else { Utils.LogErrorAndExit(string.Format("\n错误:数据库中不存在名为{0}的数据表,请检查配置中声明的导出数据表名与数据库是否对应", tableName)); } } Utils.Log("\n按任意键退出本工具"); Console.ReadKey(); }
private void btnCompare_Click(object sender, EventArgs e) { rtxResult.Text = string.Empty; string errorString = null; // 检查新旧数据库连接字符串是否输入 AppValues.ConnectStringForOldDatabase = txtOldConnString.Text.Trim(); AppValues.ConnectStringForNewDatabase = txtNewConnString.Text.Trim(); if (string.IsNullOrEmpty(AppValues.ConnectStringForOldDatabase)) { MessageBox.Show("必须输入旧版数据库连接字符串", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (string.IsNullOrEmpty(AppValues.ConnectStringForNewDatabase)) { MessageBox.Show("必须输入新版数据库连接字符串", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (AppValues.ConnectStringForOldDatabase.Equals(AppValues.ConnectStringForNewDatabase)) { MessageBox.Show("输入的新旧两数据库连接字符串重复", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // 检查配置文件 AppValues.ConfigFilePath = txtConfigPath.Text.Trim(); if (string.IsNullOrEmpty(AppValues.ConfigFilePath)) { DialogResult dialogResult = MessageBox.Show("未指定配置文件,本工具将默认比较两数据库中所有表格的结构和数据,确定要这样做吗?\n\n点击“是”进行默认比较,点击“否”放弃", "警告", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (dialogResult == DialogResult.No) { return; } else { AppValues.AllTableCompareRule = new Dictionary <string, TableCompareRule>(); } } else { Utils.AppendOutputText("读取配置文件:", OutputType.Comment); AppValues.AllTableCompareRule = ConfigReader.LoadConfig(AppValues.ConfigFilePath, out errorString); if (!string.IsNullOrEmpty(errorString)) { MessageBox.Show(string.Concat("配置文件中存在以下错误,请修正后重试:\n\n", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } else { Utils.AppendOutputText("成功\n", OutputType.None); } } // 连接两数据库 Utils.AppendOutputText("连接旧版数据库:", OutputType.Comment); MySQLOperateHelper.ConnectToDatabase(AppValues.ConnectStringForOldDatabase, out AppValues.OldConn, out AppValues.OldSchemaName, out AppValues.OldExistTableNames, out errorString); if (!string.IsNullOrEmpty(errorString)) { MessageBox.Show(string.Concat("连接旧版数据库失败,错误原因为:", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } else { Utils.AppendOutputText("成功\n", OutputType.None); } Utils.AppendOutputText("连接新版数据库:", OutputType.Comment); MySQLOperateHelper.ConnectToDatabase(AppValues.ConnectStringForNewDatabase, out AppValues.NewConn, out AppValues.NewSchemaName, out AppValues.NewExistTableNames, out errorString); if (!string.IsNullOrEmpty(errorString)) { MessageBox.Show(string.Concat("连接新版数据库失败,错误原因为:", errorString), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } else { Utils.AppendOutputText("成功\n", OutputType.None); } // 整理数据库结构信息 Utils.AppendOutputText("分析旧版数据库表结构:", OutputType.Comment); AppValues.OldTableInfo = new Dictionary <string, TableInfo>(); foreach (string tableName in AppValues.OldExistTableNames) { TableInfo tableInfo = MySQLOperateHelper.GetTableInfo(AppValues.OldSchemaName, tableName, AppValues.OldConn); AppValues.OldTableInfo.Add(tableName, tableInfo); } Utils.AppendOutputText("成功\n", OutputType.None); Utils.AppendOutputText("分析新版数据库表结构:", OutputType.Comment); AppValues.NewTableInfo = new Dictionary <string, TableInfo>(); foreach (string tableName in AppValues.NewExistTableNames) { TableInfo tableInfo = MySQLOperateHelper.GetTableInfo(AppValues.NewSchemaName, tableName, AppValues.NewConn); AppValues.NewTableInfo.Add(tableName, tableInfo); } Utils.AppendOutputText("成功\n", OutputType.None); Utils.AppendOutputText("\n", OutputType.None); // 进行对比,并展示结果 MySQLOperateHelper.CompareAndShowResult(out errorString); if (!string.IsNullOrEmpty(errorString)) { string tips = string.Concat("对比中发现以下问题,请修正后重新进行比较:\n\n", errorString); MessageBox.Show(tips, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { Utils.AppendOutputText("\n", OutputType.Comment); Utils.AppendOutputText("对比完毕", OutputType.Comment); } }