本文仍然属于一个自动生成代码工具。
上一篇我们根据数据库表的信息,自动生成实体类.cs文件。这次我们根据Excel配置,直接生成CRUD以及窗体列表和编辑界面相关的程序源文件。
通过自动生成代码,这样可以大大减少我们的开发工作量。
在原来的应用程序AutoGenerateForm添加对NPOI类库的引用,用于读写Excel文件。相关引用【NPOI.dll】【NPOI.OOXML.dll】【NPOI.OpenXml4Net.dll】【NPOI.OpenXmlFormats.dll】
excel配置文件 Conf\DataGridViewConf_Form.xls的设计如图:
关键列:
Data_Type 表示 数据类型
Field_Category 字段类型枚举:[PrimaryKey,主键列,用于更新、删除某一行记录],[BarcodeField,条码列,用于查询数据],[Normal,其他普通列]
Form_Category 表单类型枚举:代表该列在编辑区域显示的表单控件类型。该字段对应文本框、组合框、日期时间选择等组件的某一个。
Form_Visible 代表该表单是否显示
Form_Collection 用于列表或者下拉选择
Form_Min、Form_Max 数字类型时设置上下限值
Form_Location_X、Form_Location_Y 控件所在的位置坐标
新建读写Excel操作NpoiExcelOperateUtil.cs,源程序如下:
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutoGenerateForm
{
public static class NpoiExcelOperateUtil
{
#region Excel操作
/// <summary>
/// Excel的第一个工作簿(Sheet)转化成DataTable
/// 使用EXCEL的第一个工作簿,默认为Sheet1
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static DataTable ExcelToTable(string file)
{
DataTable dt = new DataTable();
IWorkbook workbook;
string fileExt = Path.GetExtension(file).ToLower();
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
//XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
if (fileExt == ".xlsx")
{
workbook = new XSSFWorkbook(fs);
}
else if (fileExt == ".xls")
{
workbook = new HSSFWorkbook(fs);
}
else
{
return null;
}
//第一个工作簿
ISheet sheet = workbook.GetSheetAt(0);
if (sheet == null)
{
return null;
}
return ExcelToTable(file, sheet.SheetName);
}
}
/// <summary>
/// Excel的指定Sheet转化成内存表
/// </summary>
/// <param name="file">路径</param>
/// <param name="sheetName">sheet名称</param>
/// <returns></returns>
public static DataTable ExcelToTable(string file, string sheetName)
{
DataTable[] dataTables = ExcelToTable(file, new List<string>() { sheetName });
if (dataTables != null && dataTables.Length > 0)
{
return dataTables[0];
}
return null;
}
/// <summary>
/// 一个excel文件的多个Sheet转化成内存表数组,
/// 每个Sheet都对应一个数据表
/// </summary>
/// <param name="file">路径</param>
/// <param name="list_SheetName">sheet名称集合</param>
/// <returns></returns>
public static DataTable[] ExcelToTable(string file, List<string> list_SheetName)
{
int count = list_SheetName.Count;
DataTable[] dtS = new DataTable[count];
//===============================//
IWorkbook workbook;
string fileExt = Path.GetExtension(file).ToLower();
using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
//XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
if (fileExt == ".xlsx")
{
workbook = new XSSFWorkbook(fs);
}
else if (fileExt == ".xls")
{
workbook = new HSSFWorkbook(fs);
}
else
{
return null;
}
ISheet[] sheetS = new ISheet[count];
for (int k = 0; k < count; k++)
{
dtS[k] = new DataTable(list_SheetName[k]);
sheetS[k] = workbook.GetSheet(list_SheetName[k]);
ISheet sheet = sheetS[k];
if (sheet == null)
{
continue;
}
DataTable dt = new DataTable(list_SheetName[k]);
//表头
IRow header = sheet.GetRow(sheet.FirstRowNum);
List<int> columns = new List<int>();
for (int i = 0; i < header.LastCellNum; i++)
{
object obj = GetValueType(header.GetCell(i));
if (obj == null || obj.ToString() == string.Empty)
{
dt.Columns.Add(new DataColumn("Columns" + i.ToString()));
}
else
dt.Columns.Add(new DataColumn(obj.ToString()));
columns.Add(i);
}
//数据
for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++)
{
DataRow dr = dt.NewRow();
bool hasValue = false;
foreach (int j in columns)
{
dr[j] = GetValueType(sheet.GetRow(i).GetCell(j));
if (dr[j] != null && dr[j].ToString() != string.Empty)
{
hasValue = true;
}
}
if (hasValue)
{
dt.Rows.Add(dr);
}
}
dtS[k] = dt;
}
}
return dtS;
}
/// <summary>
/// Datable导出成Excel
/// </summary>
/// <param name="dt"></param>
/// <param name="file"></param>
public static void TableToExcel(DataTable dt, string file)
{
IWorkbook workbook;
string fileExt = Path.GetExtension(file).ToLower();
if (fileExt == ".xlsx")
{
//workbook = new XSSFWorkbook();
workbook = new HSSFWorkbook();
}
else if (fileExt == ".xls")
{
workbook = new HSSFWorkbook();
}
else
{
workbook = null;
}
if (workbook == null)
{
return;
}
ISheet sheet = string.IsNullOrEmpty(dt.TableName) ? workbook.CreateSheet("Sheet1") : workbook.CreateSheet(dt.TableName);
//表头
IRow row = sheet.CreateRow(0);
for (int i = 0; i < dt.Columns.Count; i++)
{
ICell cell = row.CreateCell(i);
cell.SetCellValue(dt.Columns[i].ColumnName);
}
//数据
for (int i = 0; i < dt.Rows.Count; i++)
{
IRow row1 = sheet.CreateRow(i + 1);
for (int j = 0; j < dt.Columns.Count; j++)
{
ICell cell = row1.CreateCell(j);
cell.SetCellValue(dt.Rows[i][j].ToString());
}
}
//转为字节数组
MemoryStream stream = new MemoryStream();
workbook.Write(stream);
var buf = stream.ToArray();
//保存为Excel文件
using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
{
fs.Write(buf, 0, buf.Length);
fs.Flush();
}
}
/// <summary>
/// 获取单元格类型
/// </summary>
/// <param name="cell"></param>
/// <returns></returns>
private static object GetValueType(ICell cell)
{
if (cell == null)
return null;
switch (cell.CellType)
{
case CellType.Blank: //BLANK:
return null;
case CellType.Boolean: //BOOLEAN:
return cell.BooleanCellValue;
case CellType.Numeric: //NUMERIC:
return cell.NumericCellValue;
case CellType.String: //STRING:
return cell.StringCellValue;
case CellType.Error: //ERROR:
return cell.ErrorCellValue;
case CellType.Formula: //FORMULA:
default:
return "=" + cell.CellFormula;
}
}
/// <summary>
/// 重命名列
/// </summary>
/// <param name="dt"></param>
/// <param name="oldName"></param>
/// <param name="newName"></param>
public static void ReNameColumnName(DataTable dt, string oldName, string newName)
{
if (dt.Columns.Contains(oldName))
{
dt.Columns[oldName].ColumnName = newName;
}
}
#endregion
}
}
原来的RawSql.cs增加自定义查询数据,整体RawSql.cs 如下:
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutoGenerateForm
{
/// <summary>
/// 原生的sql增删改查
/// </summary>
public class RawSql
{
/// <summary>
/// 执行原生的Sql与sql参数的insert、update、delete等操作,返回受影响的行数
/// </summary>
/// <param name="sql"></param>
/// <param name="dict"></param>
/// <param name="dbType">数据库类型,一般是mysql</param>
/// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
/// <returns></returns>
public static int ExecuteCommand(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
{
List<SugarParameter> parameters = DictToList(dict);
using (var db = SugarDao.GetInstance(dbType, index))
{
return db.Ado.ExecuteCommand(sql, parameters);
}
}
/// <summary>
/// 执行原生的Sql与sql参数的select查询等操作,返回首行首列的数据
/// </summary>
/// <param name="sql"></param>
/// <param name="dict"></param>
/// <param name="dbType">数据库类型,一般是mysql</param>
/// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
/// <returns></returns>
public static object GetScalar(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
{
List<SugarParameter> parameters = DictToList(dict);
using (var db = SugarDao.GetInstance(dbType, index))
{
return db.Ado.GetScalar(sql, parameters);
}
}
/// <summary>
/// 执行原生的Sql与sql参数的select查询等操作,返回一个数据表
/// </summary>
/// <param name="sql"></param>
/// <param name="dict"></param>
/// <param name="dbType">数据库类型,一般是mysql</param>
/// <param name="index">额外的连接数据库,2为新的数据库连接字符串</param>
/// <returns></returns>
public static DataTable GetDataTable(string sql, Dictionary<string, object> dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1)
{
List<SugarParameter> parameters = DictToList(dict);
using (var db = SugarDao.GetInstance(dbType, index))
{
return db.Ado.GetDataTable(sql, parameters);
}
}
/// <summary>
/// 字典转参数列表
/// </summary>
/// <param name="dict"></param>
/// <returns></returns>
private static List<SugarParameter> DictToList(Dictionary<string, object> dict)
{
List<SugarParameter> parameters = new List<SugarParameter>();
for (int i = 0; dict != null && i < dict.Count; i++)
{
KeyValuePair<string, object> keyValuePair = dict.ElementAt(i);
parameters.Add(new SugarParameter(keyValuePair.Key, keyValuePair.Value));
}
return parameters;
}
/// <summary>
/// 查询表的相关项,生成一个内存表
/// </summary>
/// <param name="selectItems"></param>
/// <param name="where_expression"></param>
/// <param name="dictAddPara"></param>
/// <param name="tableName"></param>
/// <param name="tableNameAs"></param>
/// <param name="orderfild"></param>
/// <returns></returns>
public static DataTable Select_By_Expression(string selectItems, string where_expression, Dictionary<string, object> dictAddPara, string tableName, string tableNameAs, string orderfild = "")
{
DataTable dataTable = new DataTable(tableName);
using (var db = SugarDao.GetInstance())
{
if (!selectItems.Contains(orderfild))
{
orderfild = "";
}
var datax = db.Queryable(tableName, tableNameAs).Where(where_expression).AddParameters(dictAddPara).Select(selectItems).OrderByIF(orderfild != "", orderfild);
try
{
dataTable = datax.ToDataTable();
}
catch (Exception ex)
{
Console.WriteLine($"【查询出现异常】表【{tableName}】-{ex.Message}");
}
return dataTable;
}
}
}
}
新增类 CSVTitleName.cs,用于保存列的数据类型,字段类型是主键列、条码列、普通列。源程序
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutoGenerateForm
{
/// <summary>
/// CSV标题头实体类
/// </summary>
public class CSVTitleName
{
/// <summary>
/// 中文名称【列的注释信息】
/// </summary>
public string ChineseName { get; set; }
/// <summary>
/// 英文名称【列名、字段名】
/// </summary>
public string EnglishName { get; set; }
/// <summary>
/// 列的数据类型
/// </summary>
public string DataType { get; set; }
/// <summary>
/// 字段类型:主键字段、条码字段、普通字段
/// 用于 生成【CRUD】类的相关操作是查找条码字段
/// </summary>
public string FieldCategory { get; set; }
}
}
生成表单的三个辅助类AutoGenerateUtil.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm
{
/// <summary>
/// 自动生成窗体相关控件代码 以及绑定内容,以及读取控件的值绑定到实体类的属性上等相关操作类
/// 斯内科 2021-02-01
/// </summary>
public class AutoGenerateUtil
{
/// <summary>
/// 获取主键列 和 条码列的名称
/// </summary>
/// <param name="_primaryKeyField"></param>
/// <param name="_barcodeField"></param>
public static void GetPrimaryKeyAndBarcodeField<T>(out string _primaryKeyField, out string _barcodeField)
{
_primaryKeyField = "CoreId";
_barcodeField = "Barcode";
Type type = typeof(T);
//调用实例化方法(非静态方法)需要创建类型的一个实例
object instanceObject = Activator.CreateInstance(type);
//遍历所有可交互控件,获取控件的Tag以及对应的值,并为属性赋值
IEnumerable<PropertyInfo> propertyCollection = type.GetProperties().Where(property => property.CustomAttributes.Count() > 0);
//查找主键列名
PropertyInfo propertyPrimaryKey = propertyCollection.Where(property => property.CustomAttributes.
Where(attrData => attrData.NamedArguments.Where(attrArg => attrArg.MemberName == "IsPrimaryKey").Count() > 0).Count() > 0).FirstOrDefault();
if (propertyPrimaryKey == null)
{
MessageBox.Show("没有配置实体类的主键列特性:IsPrimaryKey");
return;
}
_primaryKeyField = propertyPrimaryKey.Name;
//找到指定的条码列 [SqlSugar.SugarColumn(ColumnDescription = "Barcode")]
PropertyInfo propertyBarcode = propertyCollection.Where(property => property.CustomAttributes.
Where(attrData => attrData.NamedArguments.Where(attrArg => attrArg.MemberName == "ColumnDescription" && Convert.ToString(attrArg.TypedValue.Value) == "Barcode").Count() > 0).Count() > 0).FirstOrDefault();
if (propertyBarcode == null)
{
MessageBox.Show($"没有配置实体类的条码列【查询条件列】特性:ColumnDescription = \"Barcode\"");
return;
}
_barcodeField = propertyBarcode.Name;
}
/// <summary>
/// 使用表设计器初始化DataGridView的列绑定,以及增加 编辑和删除列
/// </summary>
/// <param name="dt"></param>
/// <param name="dgw_Data"></param>
public static void InitialDataGridViewColumns(DataTable dt, DataGridView dgw_Data)
{
dgw_Data.AutoGenerateColumns = false;
DataGridViewUtil.DataGridViewIni(dt, ref dgw_Data);
//增加编辑、删除列
DataGridViewButtonColumn dgvcEdit = new DataGridViewButtonColumn();
dgvcEdit.Name = "dgvcEdit";
dgvcEdit.HeaderText = "编辑";
dgvcEdit.Text = "编辑";
dgvcEdit.ReadOnly = true;
dgvcEdit.UseColumnTextForButtonValue = true;//显示按钮列的单元格的文本
dgw_Data.Columns.Add(dgvcEdit);
DataGridViewButtonColumn dgvcDelete = new DataGridViewButtonColumn();
dgvcDelete.Name = "dgvcDelete";
dgvcDelete.HeaderText = "删除";
dgvcDelete.Text = "删除";
dgvcDelete.ReadOnly = true;
dgvcDelete.UseColumnTextForButtonValue = true;
dgw_Data.Columns.Add(dgvcDelete);
}
/// <summary>
/// 绑定查询的数据到DataGridView上
/// </summary>
/// <param name="keyword">查询的条件</param>
/// <param name="barcodeField">查询的字段</param>
/// <param name="selectItemCollection">选择的列集合,以逗号拼接</param>
/// <param name="currentTableName">查询的表名</param>
/// <param name="dgw_Data">要绑定的DataGridView</param>
public static void BindDataList(string keyword, string barcodeField, string selectItemCollection, string currentTableName, DataGridView dgw_Data)
{
string tableNameAs = "tb";//表的别名
Dictionary<string, object> dictAddPara = new Dictionary<string, object>();//SQL中的参数以及对应的值
List<string> conditionCollection = new List<string>();
//如果关键字不为空
if (keyword.Length > 0)
{
conditionCollection.Add($"{tableNameAs}.{barcodeField}=@PackBarcode");
dictAddPara.Add("PackBarcode", keyword);
}
//默认使用and连接
string where_expression = string.Join(" and ", conditionCollection);
string tableName = currentTableName;//查找的表名
DataTable dtTemp = new DataTable(currentTableName);
dtTemp = RawSql.Select_By_Expression(selectItemCollection, where_expression, dictAddPara, tableName, tableNameAs);
dgw_Data.DataSource = dtTemp;
}
/// <summary>
/// 初始化创建相关设计类的所有控件信息
/// </summary>
/// <param name="dt"></param>
/// <param name="form"></param>
public static void InitialCreateControls(DataTable dt, Form form)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
string formVisible = dt.Rows[i]["Form_Visible"].ToString();
if (formVisible != "1")
{
//如果不显示就 忽略
continue;
}
string chineseName = dt.Rows[i]["Ch_Name"].ToString();//标签中文名
string englishName = dt.Rows[i]["En_Name"].ToString();//英文名
string dataType = dt.Rows[i]["Data_Type"].ToString();//数据类型
string defaultValue = dt.Rows[i]["Default_Value"].ToString();//默认值
string formCollection = dt.Rows[i]["Form_Collection"].ToString();//组合下拉框 或者 单选按钮的项集合,使用|(竖线)分割
string formMin = dt.Rows[i]["Form_Min"].ToString();//数字显示框的下限值
string formMax = dt.Rows[i]["Form_Max"].ToString();//数字显示框的上限值
string formLocationX = dt.Rows[i]["Form_Location_X"].ToString();//起始位置坐标X
string formLocationY = dt.Rows[i]["Form_Location_Y"].ToString();//起始位置坐标Y
int locationX;//X坐标
int locationY;//Y坐标
int.TryParse(formLocationX, out locationX);
int.TryParse(formLocationY, out locationY);
FormCategory formCategory;
if (!Enum.TryParse(dt.Rows[i]["Form_Category"].ToString(), true, out formCategory))
{
//默认使用文本框
formCategory = FormCategory.TextBox;
}
Label lbl = AutoGenerateUtil.SetLabel(chineseName, englishName, locationX + 5 - 120, locationY);
switch (formCategory)
{
case FormCategory.None:
break;
case FormCategory.TextBox:
form.Controls.Add(lbl);//增加标签显示
TextBox txb = SetTextBox(englishName, defaultValue, locationX, locationY);
form.Controls.Add(txb);
break;
case FormCategory.ComboBox:
form.Controls.Add(lbl);//增加标签显示
ComboBox cbo = SetComboBox(englishName, defaultValue, formCollection, locationX, locationY);
form.Controls.Add(cbo);
break;
case FormCategory.RadioButton:
form.Controls.Add(lbl);//增加标签显示
//这里使用GroupBox包含所有的单选按钮
GroupBox grp = SetGroupAndRadioButton(englishName, formCollection, locationX, locationY);
form.Controls.Add(grp);
break;
case FormCategory.DateTimePicker:
form.Controls.Add(lbl);//增加标签显示
DateTimePicker dtp = SetDateTimePicker(englishName, locationX, locationY);
form.Controls.Add(dtp);
break;
case FormCategory.NumericUpDown:
form.Controls.Add(lbl);//增加标签显示
NumericUpDown numericUpDown = SetNumericUpDown(englishName, dataType, formMin, formMax, locationX, locationY);
form.Controls.Add(numericUpDown);
break;
}
}
}
/// <summary>
/// 绑定控件的初始值【从数据库中读取】
/// </summary>
/// <param name="dataTable"></param>
public static void BindControlValue(DataTable dataTable, Form form)
{
if (dataTable == null || dataTable.Rows.Count < 1)
{
return;
}
DataRow dataRow = dataTable.Rows[0];
for (int i = 0; i < form.Controls.Count; i++)
{
Control control = form.Controls[i];
if (control is Label || control is Button || control.Tag == null)
{
//不考虑标签 或者 Tag为null的控件
continue;
}
string fieldName = Convert.ToString(control.Tag);
//NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
if (control is NumericUpDown)
{
fieldName = (control.Tag as Tuple<string, string>).Item1;
}
//如果数据表的列集合中不含有该字段,则忽略
if (!dataTable.Columns.Contains(fieldName))
{
continue;
}
//为指定的控件赋值
if (control is TextBox)
{
((TextBox)control).Text = dataRow[fieldName].ToString();
}
else if (control is ComboBox)
{
ComboBox cbo = control as ComboBox;
for (int index = 0; index < cbo.Items.Count; index++)
{
if (cbo.Items[index].ToString() == dataRow[fieldName].ToString())
{
cbo.SelectedIndex = index;
break;
}
}
}
else if (control is GroupBox)
{
//设置RadioButton的选中
GroupBox grp = control as GroupBox;
for (int index = 0; index < grp.Controls.Count; index++)
{
RadioButton rdo = grp.Controls[index] as RadioButton;
if (rdo != null && rdo.Text == dataRow[fieldName].ToString())
{
rdo.Checked = true;
break;
}
else if (rdo != null)
{
rdo.Checked = false;
}
}
}
else if (control is DateTimePicker)
{
((DateTimePicker)control).Value = Convert.ToDateTime(dataRow[fieldName]);
}
else if (control is NumericUpDown)
{
((NumericUpDown)control).Value = Convert.ToDecimal(dataRow[fieldName]);
}
}
}
/// <summary>
/// 遍历所有可交互控件,获取控件的Tag以及对应的值,并为实体类的对应属性赋值
/// </summary>
/// <param name="type"></param>
/// <param name="instanceObject"></param>
public static void SetInstanceObjectPropertyValues(Type type, object instanceObject, Form form)
{
for (int i = 0; i < form.Controls.Count; i++)
{
Control control = form.Controls[i];
if (control is Label || control is Button || control.Tag == null)
{
//不考虑标签 或者 Tag为null的控件
continue;
}
//找出控件的数据对象 也就是属性名(字段名、列名)
string fieldName = Convert.ToString(control.Tag);
//NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
if (control is NumericUpDown)
{
fieldName = (control.Tag as Tuple<string, string>).Item1;
}
PropertyInfo propertyInfoName = type.GetProperty(fieldName);
//如果类不存在该属性,则忽略
if (propertyInfoName == null)
{
continue;
}
//为指定的控件赋值
if (control is TextBox)
{
propertyInfoName.SetValue(instanceObject, ((TextBox)control).Text);
}
else if (control is ComboBox)
{
ComboBox cbo = control as ComboBox;
propertyInfoName.SetValue(instanceObject, ((ComboBox)control).Text);
}
else if (control is GroupBox)
{
//设置RadioButton的选中
GroupBox grp = control as GroupBox;
for (int index = 0; index < grp.Controls.Count; index++)
{
RadioButton rdo = grp.Controls[index] as RadioButton;
if (rdo != null && rdo.Checked)
{
propertyInfoName.SetValue(instanceObject, rdo.Text);
break;
}
}
}
else if (control is DateTimePicker)
{
propertyInfoName.SetValue(instanceObject, ((DateTimePicker)control).Value);
}
else if (control is NumericUpDown)
{
NumericUpDown numericUpDown = control as NumericUpDown;
string dataType = (numericUpDown.Tag as Tuple<string, string>).Item2;
if (dataType != null && dataType.IndexOf("int", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
propertyInfoName.SetValue(instanceObject, Convert.ToInt32(numericUpDown.Value));
}
else if (dataType != null && dataType.IndexOf("decimal", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
propertyInfoName.SetValue(instanceObject, numericUpDown.Value);
}
else
{
propertyInfoName.SetValue(instanceObject, Convert.ToSingle(numericUpDown.Value));
}
}
}
}
/// <summary>
/// 设置Label标签控件
/// </summary>
/// <param name="chineseName"></param>
/// <param name="englishName"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static Label SetLabel(string chineseName, string englishName, int locationX, int locationY)
{
Label lbl = new Label();
//如果字体较多 就设置为两行。如果字体的宽度少于16个空格【八个中文宽度大小】,就补充空格数:(16 - bufferSize.Length)
byte[] bufferSize = Encoding.GetEncoding("gbk").GetBytes(chineseName);
if (bufferSize.Length > 16)
{
lbl.Size = new Size(110, 26);
}
else
{
chineseName = chineseName.PadLeft(chineseName.Length + 16 - bufferSize.Length);
lbl.AutoSize = true;
}
lbl.Name = $"lbl{englishName}";
lbl.Text = chineseName;
lbl.Location = new Point(locationX, locationY);
return lbl;
}
/// <summary>
/// 设置文本框控件
/// </summary>
/// <param name="englishName"></param>
/// <param name="defaultValue"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static TextBox SetTextBox(string englishName, string defaultValue, int locationX, int locationY)
{
TextBox txb = new TextBox();
txb.Name = $"txb{englishName}";
txb.Text = defaultValue;
txb.Location = new Point(locationX, locationY);
txb.Size = new Size(200, 21);
txb.Tag = englishName;//增加控件 绑定的列名(字段名)
return txb;
}
/// <summary>
/// 设置组合框控件
/// </summary>
/// <param name="englishName"></param>
/// <param name="defaultValue"></param>
/// <param name="formCollection"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static ComboBox SetComboBox(string englishName, string defaultValue, string formCollection, int locationX, int locationY)
{
ComboBox cbo = new ComboBox();
cbo.Name = $"cbo{englishName}";
cbo.Text = defaultValue;
cbo.Location = new Point(locationX, locationY);
if (!string.IsNullOrEmpty(formCollection))
{
string[] itemArray = formCollection.Split('|');
for (int index = 0; index < itemArray.Length; index++)
{
cbo.Items.Add(itemArray[index]);
}
}
cbo.Size = new Size(200, 21);
cbo.Tag = englishName;//增加控件 绑定的列名(字段名)
return cbo;
}
/// <summary>
/// 设置分组框和单选按钮集合【多个单选按钮放入在同一个分组框中】
/// </summary>
/// <param name="englishName"></param>
/// <param name="formCollection"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static GroupBox SetGroupAndRadioButton(string englishName, string formCollection, int locationX, int locationY)
{
//这里使用GroupBox包含所有的单选按钮
GroupBox grp = new GroupBox();
grp.Name = $"grp{englishName}";
//grp.Text = chineseName;
grp.Location = new Point(locationX, locationY - 20);
grp.Size = new Size(200, 40);
grp.Tag = englishName;//增加控件 绑定的列名(字段名)
if (string.IsNullOrEmpty(formCollection))
{
formCollection = "选项一";
}
string[] itemArr = formCollection.Split('|');
for (int index = 0; index < itemArr.Length; index++)
{
RadioButton rdo = new RadioButton();
rdo.Name = $"rdo{englishName}{index + 1}";
rdo.Text = itemArr[index];
rdo.Location = new Point(10 + 70 * index, 20);
rdo.AutoSize = true;
if (index == 0)
{
rdo.Checked = true;//设置第一项为选中
}
grp.Controls.Add(rdo);
}
return grp;
}
/// <summary>
/// 设置日期时间选择控件
/// </summary>
/// <param name="englishName"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static DateTimePicker SetDateTimePicker(string englishName, int locationX, int locationY)
{
DateTimePicker dtp = new DateTimePicker();
dtp.Name = $"dtp{englishName}";
dtp.Value = DateTime.Now;
dtp.Location = new Point(locationX, locationY);
dtp.Format = DateTimePickerFormat.Custom; //设置日期格式为2020-08-05
dtp.CustomFormat = "yyyy-MM-dd HH:mm:ss";
dtp.Tag = englishName;//增加控件 绑定的列名(字段名)
return dtp;
}
/// <summary>
/// 设置数字显示框控件
/// NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
/// </summary>
/// <param name="englishName"></param>
/// <param name="dataType"></param>
/// <param name="formMin"></param>
/// <param name="formMax"></param>
/// <param name="locationX"></param>
/// <param name="locationY"></param>
/// <returns></returns>
private static NumericUpDown SetNumericUpDown(string englishName, string dataType, string formMin, string formMax, int locationX, int locationY)
{
NumericUpDown numericUpDown = new NumericUpDown();
numericUpDown.Name = $"numericUpDown{englishName}";
//numericUpDown.Value = DateTime.Now;
numericUpDown.Location = new Point(locationX, locationY);
numericUpDown.Size = new Size(200, 121);
decimal decMin;
decimal decMax;
decimal.TryParse(formMin, out decMin);
decimal.TryParse(formMax, out decMax);
numericUpDown.Minimum = decMin;
if (decMax > decMin)
{
numericUpDown.Maximum = decMax;
}
//如果是int类型
if (dataType != null && dataType.IndexOf("int", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
numericUpDown.DecimalPlaces = 0;
}
else if (dataType != null && dataType.IndexOf("decimal", StringComparison.CurrentCultureIgnoreCase) >= 0)
{
//decimal设置为4位小数
numericUpDown.DecimalPlaces = 4;
}
else
{
//float,double设置为2位小数
numericUpDown.DecimalPlaces = 2;
}
//NumericUpDown控件的Tag特殊处理,使用二元组,第一个项代表绑定的列名(字段名),第二个项代表数据类型
numericUpDown.Tag = Tuple.Create(englishName, dataType);//增加控件 绑定的列名(字段名)
return numericUpDown;
}
}
/// <summary>
/// 表单(字段)对应的控件类型
/// </summary>
public enum FormCategory
{
/// <summary>
/// 自增或者默认当前时间的字段显示
/// </summary>
None = -1,
/// <summary>
/// 文本框,比如条码
/// </summary>
TextBox = 0,
/// <summary>
/// 组合框,下拉等选项
/// </summary>
ComboBox = 1,
/// <summary>
/// 单选按钮控件
/// </summary>
RadioButton = 2,
/// <summary>
/// 日期时间字段
/// </summary>
DateTimePicker = 3,
/// <summary>
/// 数字显示框
/// </summary>
NumericUpDown = 4
}
}
辅助类DataGridViewUtil.cs,源程序
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm
{
/// <summary>
/// 将Excel的配置映射到一个内存数据表中,然后为DataGridView设置数据绑定,以及自动生成列
/// </summary>
public class DataGridViewUtil
{
/// <summary>
/// 初始化设置DataGridView的列和相关数据绑定
/// </summary>
/// <param name="dt"></param>
/// <param name="dgvw"></param>
public static void DataGridViewIni(DataTable dt, ref DataGridView dgvw)
{
dgvw.Columns.Clear();
string tableName = dt.TableName;
try
{
if (dt != null && dt.Rows.Count > 0)
{
if (!dt.Columns.Contains("En_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在En_Name列");
return;
}
if (!dt.Columns.Contains("Another_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Another_Name列");
return;
}
if (!dt.Columns.Contains("Use"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Use列");
return;
}
if (!dt.Columns.Contains("Table_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Table_Name列");
return;
}
int columnCount = dt.Rows.Count;
if (dt.Rows[0]["Table_Name"] == null || tableName != dt.Rows[0]["Table_Name"].ToString().Trim())
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--表名与表中Table_Name不匹配");
return;
}
for (int i = 0; i < columnCount; i++)
{
string isUse = dt.Rows[i]["Use"].ToString().Trim();
if (isUse != "1")
{
continue;//不添加
}
string columnName = dt.Rows[i]["En_Name"].ToString();
string columnDescription = dt.Rows[i]["Another_Name"].ToString();
DataGridViewColumn dgvc = new DataGridViewColumn();
dgvc.CellTemplate = new DataGridViewTextBoxCell();
dgvc.Name = "dgvc_" + columnName;
int minWidth = 50;
bool rtn = int.TryParse(dt.Rows[i]["Min_Width"].ToString(), out minWidth);
if (!rtn)
{
minWidth = 50;
}
dgvc.MinimumWidth = minWidth;
dgvc.DataPropertyName = columnName;
dgvc.HeaderText = (columnDescription == null || columnDescription.Trim().Length == 0) ? columnName : columnDescription;
dgvw.Columns.Add(dgvc);
}
}
}
catch (Exception ex)
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查:" + ex.Message);
}
return;
}
}
}
辅助模板类GenerateUtil.cs,源程序
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm
{
/// <summary>
/// 自动生成相关操作
/// </summary>
public class GenerateUtil
{
/// <summary>
/// 获取表的字段类型信息 标记字段是主键字段、条码字段等
/// </summary>
/// <param name="xlsfilePath"></param>
/// <param name="tableName"></param>
/// <returns></returns>
public static List<CSVTitleName> GetFieldInfo(string xlsfilePath, string tableName)
{
List<CSVTitleName> list = new List<CSVTitleName>();
DataTable dt = NpoiExcelOperateUtil.ExcelToTable(xlsfilePath, tableName);
if (dt == null || dt.Rows.Count == 0)
{
MessageBox.Show($"{tableName}没有配置表的任何数据");
return list;
}
if (!dt.Columns.Contains("Table_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Table_Name列");
return list;
}
if (!dt.Columns.Contains("En_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在En_Name列");
return list;
}
if (!dt.Columns.Contains("Ch_Name"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Ch_Name列");
return list;
}
if (!dt.Columns.Contains("Data_Type"))
{
MessageBox.Show($"{tableName}表的UI配置文件错误,请检查--不存在Data_Type列");
return list;
}
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
//如果包含 字段类型列,就读取字段类型 斯内科 20210129
string fieldCategory = "Normal";
if (dt.Columns.Contains("Field_Category") && !string.IsNullOrEmpty(dr["Field_Category"].ToString()))
{
fieldCategory = dr["Field_Category"].ToString();
}
CSVTitleName csvTitleName = new CSVTitleName()
{
ChineseName = dr["Ch_Name"].ToString(),
EnglishName = dr["En_Name"].ToString(),
DataType = dr["Data_Type"].ToString(),
FieldCategory = fieldCategory
};
list.Add(csvTitleName);
}
return list;
}
/// <summary>
/// 获得CRUD文件内容:配置类名(表名)、条码字段、主键字段
/// </summary>
/// <param name="className">类名(表名)</param>
/// <param name="fieldBarcode">条码字段</param>
/// <param name="fieldPrimaryKey">主键字段</param>
/// <returns></returns>
public static string GetCRUDFileContent(string className, string fieldBarcode, string fieldPrimaryKey)
{
return $@"using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using SqlSugar;
using AutoGenerateForm.Models;
namespace AutoGenerateForm.CRUD
{
{
public class CRUD_{className}
{
{
public static int Insert({className} {className}Obj)
{
{
//添加一条数据
using (var db = SugarDao.GetInstance())
{
{
return db.Insertable({className}Obj).ExecuteCommand();
}}
}}
public static int Update({className} {className}Obj, int coreId)
{
{
//更新一条数据 按照 主键
using (var db = SugarDao.GetInstance())
{
{
return db.Updateable({className}Obj).Where(tObj => tObj.{fieldPrimaryKey} == coreId).ExecuteCommand();
}}
}}
public static void DeleteByBarcode(string barcode)
{
{
//根据条码删除
using (var db = SugarDao.GetInstance())
{
{
db.Deleteable<{className}>(it => it.{fieldBarcode} == barcode).ExecuteCommand();
}}
}}
public static void DeleteByCoreId(int coreId)
{
{
//根据主键删除
using (var db = SugarDao.GetInstance())
{
{
db.Deleteable<{className}>(it => it.{fieldPrimaryKey} == coreId).ExecuteCommand();
}}
}}
public static DataTable SelectByBarcode(string barcode)
{
{
DataTable dataTable = new DataTable(""xxx"");
using (var db = SugarDao.GetInstance())
{
{
var dataS = db.Queryable<{className}>().Where(it => it.{fieldBarcode} == barcode);
dataTable = dataS.ToDataTable();
}}
return dataTable;
}}
public static DataTable SelectByCoreId(int coreId)
{
{
DataTable dataTable = new DataTable(""xxx"");
using (var db = SugarDao.GetInstance())
{
{
var dataS = db.Queryable<{className}>().Where(it => it.{fieldPrimaryKey} == coreId);
dataTable = dataS.ToDataTable();
}}
return dataTable;
}}
}}
}}";
}
/// <summary>
/// 获取窗体【编辑】的设计器的文件内容
/// </summary>
/// <param name="className"></param>
/// <returns></returns>
public static string GetFormDesignerContent(string className)
{
return $@"namespace AutoGenerateForm.Forms
{
{
partial class Frm{className}Edit
{
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name=""disposing"">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
{
if (disposing && (components != null))
{
{
components.Dispose();
}}
base.Dispose(disposing);
}}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
{
this.btnSave = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnSave
//
this.btnSave.Font = new System.Drawing.Font(""宋体"", 13F);
this.btnSave.Location = new System.Drawing.Point(543, 527);
this.btnSave.Name = ""btnSave"";
this.btnSave.Size = new System.Drawing.Size(73, 41);
this.btnSave.TabIndex = 0;
this.btnSave.Text = ""保存"";
this.btnSave.UseVisualStyleBackColor = true;
this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
//
// btnCancel
//
this.btnCancel.Font = new System.Drawing.Font(""宋体"", 13F);
this.btnCancel.Location = new System.Drawing.Point(653, 527);
this.btnCancel.Name = ""btnCancel"";
this.btnCancel.Size = new System.Drawing.Size(73, 41);
this.btnCancel.TabIndex = 1;
this.btnCancel.Text = ""关闭"";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// Frm{className}Edit
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 650);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnSave);
this.Name = ""Frm{className}Edit"";
this.Text = ""Frm{className}Edit"";
this.Load += new System.EventHandler(this.Frm{className}Edit_Load);
this.ResumeLayout(false);
}}
#endregion
private System.Windows.Forms.Button btnSave;
private System.Windows.Forms.Button btnCancel;
}}
}}";
}
/// <summary>
/// 获取窗体【编辑】的文件内容
/// </summary>
/// <param name="className"></param>
/// <param name="fieldPrimaryKey"></param>
/// <returns></returns>
public static string GetFormMainContent(string className, string fieldPrimaryKey)
{
return $@"using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm.Forms
{
{
public partial class Frm{className}Edit : Form
{
{
/// <summary>
/// 添加(insert) 还是 修改(update)表单
/// </summary>
bool isAdd = true;
int coreId = -1;
DataTable dt = new DataTable(""FormDesign"");
/// <summary>
/// 表名 或者 Excel工作簿名
/// </summary>
string CurrentTableName = ""test_msg"";
public Frm{className}Edit(string sheetName)
{
{
InitializeComponent();
isAdd = true;
CurrentTableName = sheetName;
dt = NpoiExcelOperateUtil.ExcelToTable(AppDomain.CurrentDomain.BaseDirectory + ""Conf\\DataGridViewConf_Form.xls"", sheetName);
}}
public Frm{className}Edit(int _coreId, string sheetName) : this(sheetName)
{
{
coreId = _coreId;
isAdd = false;
}}
private void Frm{className}Edit_Load(object sender, EventArgs e)
{
{
AutoGenerateUtil.InitialCreateControls(dt, this);
//如果是修改表单,则从数据库中读取数据行,并为文本框赋值
if (!isAdd)
{
{
DataTable dataTable = AutoGenerateForm.CRUD.CRUD_{className}.SelectByCoreId(coreId);
if (dataTable == null || dataTable.Rows.Count < 1)
{
{
MessageBox.Show($""没有找到符合条件的记录,该行数据不存在或者已经被删除,当前编号【{
{coreId}}】"");
return;
}}
AutoGenerateUtil.BindControlValue(dataTable, this);
}}
}}
private void btnSave_Click(object sender, EventArgs e)
{
{
try
{
{
Type type = typeof(AutoGenerateForm.Models.{className});
//调用实例化方法(非静态方法)需要创建类型的一个实例
object instanceObject = Activator.CreateInstance(type);
//遍历所有可交互控件,获取控件的Tag以及对应的值,并为属性赋值
AutoGenerateUtil.SetInstanceObjectPropertyValues(type, instanceObject, this);
AutoGenerateForm.Models.{className} {className}Obj = instanceObject as AutoGenerateForm.Models.{className};
int affectCount = -1;
if (isAdd)
{
{
affectCount = AutoGenerateForm.CRUD.CRUD_{className}.Insert({className}Obj);
}}
else
{
{
{className}Obj.{fieldPrimaryKey} = coreId;
affectCount = AutoGenerateForm.CRUD.CRUD_{className}.Update({className}Obj, coreId);
}}
MessageBox.Show($""保存【{
{(isAdd ? ""添加"" : ""更新"")}}】表【{
{CurrentTableName}}】信息成功,受影响的行数【{
{affectCount}}】"");
this.DialogResult = DialogResult.OK;
}}
catch (Exception ex)
{
{
MessageBox.Show($""保存【{
{(isAdd ? ""添加"" : ""更新"")}}】表信息【{
{CurrentTableName}}】失败,异常信息:\n{
{ex.Message}}"");
}}
}}
private void btnCancel_Click(object sender, EventArgs e)
{
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}}
}}
}}";
}
/// <summary>
/// 获取窗体【列表】的设计器的文件内容
/// </summary>
/// <param name="className"></param>
/// <returns></returns>
public static string GetListFormDesignerContent(string className)
{
return $@"namespace AutoGenerateForm.Forms
{
{
partial class Frm{className}List
{
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name=""disposing"">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
{
if (disposing && (components != null))
{
{
components.Dispose();
}}
base.Dispose(disposing);
}}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle();
this.btnQuery = new System.Windows.Forms.Button();
this.txbBarcode_query = new System.Windows.Forms.TextBox();
this.lblCondition = new System.Windows.Forms.Label();
this.btnAdd = new System.Windows.Forms.Button();
this.dgw_Data = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.dgw_Data)).BeginInit();
this.SuspendLayout();
//
// btnQuery
//
this.btnQuery.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.btnQuery.Font = new System.Drawing.Font(""宋体"", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnQuery.Location = new System.Drawing.Point(436, 25);
this.btnQuery.Name = ""btnQuery"";
this.btnQuery.Size = new System.Drawing.Size(73, 26);
this.btnQuery.TabIndex = 211;
this.btnQuery.Text = ""查 询"";
this.btnQuery.UseVisualStyleBackColor = false;
this.btnQuery.Click += new System.EventHandler(this.btnQuery_Click);
//
// txbBarcode_query
//
this.txbBarcode_query.Font = new System.Drawing.Font(""宋体"", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.txbBarcode_query.Location = new System.Drawing.Point(86, 23);
this.txbBarcode_query.Name = ""txbBarcode_query"";
this.txbBarcode_query.Size = new System.Drawing.Size(340, 23);
this.txbBarcode_query.TabIndex = 209;
//
// lblCondition
//
this.lblCondition.AutoSize = true;
this.lblCondition.Font = new System.Drawing.Font(""宋体"", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.lblCondition.ForeColor = System.Drawing.SystemColors.ControlText;
this.lblCondition.Location = new System.Drawing.Point(32, 27);
this.lblCondition.Name = ""lblCondition"";
this.lblCondition.Size = new System.Drawing.Size(49, 14);
this.lblCondition.TabIndex = 210;
this.lblCondition.Text = ""关键字"";
//
// btnAdd
//
this.btnAdd.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.btnAdd.Font = new System.Drawing.Font(""宋体"", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnAdd.Location = new System.Drawing.Point(547, 25);
this.btnAdd.Name = ""btnAdd"";
this.btnAdd.Size = new System.Drawing.Size(73, 26);
this.btnAdd.TabIndex = 212;
this.btnAdd.Text = ""添 加"";
this.btnAdd.UseVisualStyleBackColor = false;
this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click);
//
// dgw_Data
//
this.dgw_Data.AllowUserToAddRows = false;
this.dgw_Data.AllowUserToDeleteRows = false;
dataGridViewCellStyle5.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(231)))), ((int)(((byte)(246)))), ((int)(((byte)(253)))));
this.dgw_Data.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle5;
this.dgw_Data.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells;
this.dgw_Data.BackgroundColor = System.Drawing.SystemColors.Window;
this.dgw_Data.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.dgw_Data.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
dataGridViewCellStyle6.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;
dataGridViewCellStyle6.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(246)))), ((int)(((byte)(239)))));
dataGridViewCellStyle6.Font = new System.Drawing.Font(""宋体"", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle6.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle6.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle6.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle6.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.dgw_Data.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle6;
this.dgw_Data.ColumnHeadersHeight = 25;
this.dgw_Data.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle7.BackColor = System.Drawing.Color.White;
dataGridViewCellStyle7.Font = new System.Drawing.Font(""宋体"", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle7.ForeColor = System.Drawing.Color.Black;
dataGridViewCellStyle7.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(188)))), ((int)(((byte)(240)))));
dataGridViewCellStyle7.SelectionForeColor = System.Drawing.Color.White;
dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgw_Data.DefaultCellStyle = dataGridViewCellStyle7;
this.dgw_Data.EnableHeadersVisualStyles = false;
this.dgw_Data.Font = new System.Drawing.Font(""宋体"", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.dgw_Data.Location = new System.Drawing.Point(3, 74);
this.dgw_Data.Name = ""dgw_Data"";
this.dgw_Data.ReadOnly = true;
this.dgw_Data.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None;
this.dgw_Data.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
dataGridViewCellStyle8.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle8.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle8.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle8.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
this.dgw_Data.RowsDefaultCellStyle = dataGridViewCellStyle8;
this.dgw_Data.RowTemplate.Height = 23;
this.dgw_Data.Size = new System.Drawing.Size(920, 454);
this.dgw_Data.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgw_Data_CellContentClick);
//
// Frm{className}List
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(932, 540);
this.Controls.Add(this.dgw_Data);
this.Controls.Add(this.btnAdd);
this.Controls.Add(this.btnQuery);
this.Controls.Add(this.txbBarcode_query);
this.Controls.Add(this.lblCondition);
this.Name = ""Frm{className}List"";
this.Text = ""Frm{className}List"";
this.Load += new System.EventHandler(this.Frm{className}List_Load);
((System.ComponentModel.ISupportInitialize)(this.dgw_Data)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}}
#endregion
private System.Windows.Forms.Button btnQuery;
public System.Windows.Forms.TextBox txbBarcode_query;
private System.Windows.Forms.Label lblCondition;
private System.Windows.Forms.Button btnAdd;
private System.Windows.Forms.DataGridView dgw_Data;
}}
}}";
}
/// <summary>
/// 获取窗体【列表】的文件内容
/// </summary>
/// <param name="className"></param>
/// <param name="fieldBarcode"></param>
/// <param name="fieldPrimaryKey"></param>
/// <returns></returns>
public static string GetListFormMainContent(string className, string fieldBarcode, string fieldPrimaryKey)
{
return $@"using AutoGenerateForm.CRUD;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm.Forms
{
{
public partial class Frm{className}List : Form
{
{
/// <summary>
/// 表Excel设计器
/// </summary>
DataTable dt = new DataTable(""FormDesign"");
/// <summary>
/// 表名 或者 Excel工作簿名
/// </summary>
string CurrentTableName = ""test_msg"";
/// <summary>
/// 所有英文名称集合【列集合】,以英文逗号(,)拼接
/// </summary>
string selectItems = string.Empty;
public Frm{className}List(string sheetName)
{
{
InitializeComponent();
CurrentTableName = sheetName;
dt = NpoiExcelOperateUtil.ExcelToTable(AppDomain.CurrentDomain.BaseDirectory + ""Conf\\DataGridViewConf_Form.xls"", sheetName);
//所有英文名称集合【列集合】
string[] DataPropertyNameArr = new string[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
{
DataPropertyNameArr[i] = dt.Rows[i][""En_Name""].ToString();
}}
selectItems = string.Join("","", DataPropertyNameArr);
AutoGenerateUtil.InitialDataGridViewColumns(dt, dgw_Data);
}}
private void Frm{className}List_Load(object sender, EventArgs e)
{
{
btnQuery_Click(null, e);
}}
private void btnQuery_Click(object sender, EventArgs e)
{
{
AutoGenerateUtil.BindDataList(txbBarcode_query.Text.Trim(), ""{fieldBarcode}"", selectItems, CurrentTableName, dgw_Data);
}}
private void btnAdd_Click(object sender, EventArgs e)
{
{
Frm{className}Edit frm{className}Edit = new Frm{className}Edit(CurrentTableName);
DialogResult dialog = frm{className}Edit.ShowDialog();
if (dialog == DialogResult.OK)
{
{
btnQuery_Click(null, e);//刷新
}}
}}
private void dgw_Data_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
{
if (e.RowIndex < 0 || e.ColumnIndex < 0)
{
{
return;
}}
int coreId = Convert.ToInt32(dgw_Data[""dgvc_{fieldPrimaryKey}"", e.RowIndex].Value);
if (dgw_Data.Columns[e.ColumnIndex].Name == ""dgvcEdit"") //编辑操作
{
{
Frm{className}Edit frm{className}Edit = new Frm{className}Edit(coreId, CurrentTableName);
DialogResult dialog = frm{className}Edit.ShowDialog();
if (dialog == DialogResult.OK)
{
{
btnQuery_Click(null, e);//刷新
}}
}}
else if (dgw_Data.Columns[e.ColumnIndex].Name == ""dgvcDelete"") //删除操作
{
{
DialogResult dialog = MessageBox.Show($""您确定要删除该条记录吗?一经删除,不可恢复!\n当前编号【{
{coreId}}】"", ""警告"", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dialog != DialogResult.Yes)
{
{
return;
}}
try
{
{
CRUD_{className}.DeleteByCoreId(coreId);
btnQuery_Click(null, e);
}}
catch (Exception ex)
{
{
MessageBox.Show(ex.Message, ""删除时出现异常"");
}}
}}
}}
}}
}}";
}
}
}
默认的窗体FormGenerateClass.cs设计器修改下:
窗体的主要代码 如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AutoGenerateForm
{
public partial class FormGenerateClass : Form
{
public FormGenerateClass()
{
InitializeComponent();
}
private void btnGenerate_Click(object sender, EventArgs e)
{
rtxbClassContent.Clear();
if (cboTable.SelectedIndex == -1)
{
cboTable.Focus();
DisplayInfo("没有选择相应的表名,请检查...");
return;
}
string tableName = Convert.ToString(cboTable.SelectedValue);
string tableComment = cboTable.Text;
DisplayInfo($"已选择表【{tableName}】,准备自动生成实体类...");
string sql = $@"SELECT TABLE_NAME as TableName,
column_name AS DbColumnName,
CASE WHEN left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1)='' THEN COLUMN_TYPE ELSE left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1) END AS DataType,
CAST(SUBSTRING(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)+1,LOCATE(')',COLUMN_TYPE)-LOCATE('(',COLUMN_TYPE)-1) AS signed) AS Length,
column_default AS `DefaultValue`,
column_comment AS `ColumnComment`,
CASE WHEN COLUMN_KEY = 'PRI' THEN true ELSE false END AS `IsPrimaryKey`,
CASE WHEN EXTRA='auto_increment' THEN true ELSE false END as IsIdentity,
CASE WHEN is_nullable = 'YES' THEN true ELSE false END AS `IsNullable`
FROM Information_schema.columns where TABLE_NAME='{tableName}' and TABLE_SCHEMA=(select database()) ORDER BY TABLE_NAME";
DataTable dataTable = RawSql.GetDataTable(sql, null);
if (dataTable == null || dataTable.Rows.Count == 0)
{
DisplayInfo($"没有找到表【{tableName}】的字段(列)信息...");
return;
}
string fileDirectory = AppDomain.CurrentDomain.BaseDirectory + @"AutoGenerateCodes\Models";//生成到的路径
string filePath = $"{Path.Combine(fileDirectory, tableName)}.cs";
string text = FileContentUtil.GetFileContent(tableName, tableComment, dataTable);
FileContentUtil.CreateFile(filePath, text, Encoding.UTF8);
DisplayInfo($"自动生成实体类【{tableName}】成功.实体类路径:{filePath}");
rtxbClassContent.AppendText(text);
//是否启动自动生成CRUD、窗体类
if (chkAutoGenerate.Checked)
{
//自动生成CRUD类.cs
//查找字段类型信息
List<CSVTitleName> list = GenerateUtil.GetFieldInfo(AppDomain.CurrentDomain.BaseDirectory + "Conf\\DataGridViewConf_Form.xls", tableName);
if (list == null || list.Count == 0)
{
DisplayInfo($"自动生成CRUD类【CRUD_{tableName}】失败.没有找到对应表的配置信息");
return;
}
//查找到条码字段
CSVTitleName csvBarcode = list.Find(csvName => csvName.FieldCategory.IndexOf("BarcodeField", StringComparison.CurrentCultureIgnoreCase) >= 0);
if (csvBarcode == null)
{
DisplayInfo($"自动生成CRUD类【CRUD_{tableName}】失败.没有配置条码字段【BarcodeField】");
return;
}
//查找到主键字段
CSVTitleName csvPrimaryKey = list.Find(csvName => csvName.FieldCategory.IndexOf("PrimaryKey", StringComparison.CurrentCultureIgnoreCase) >= 0);
if (csvBarcode == null)
{
DisplayInfo($"自动生成CRUD类【CRUD_{tableName}】失败.没有配置主键字段【PrimaryKey】");
return;
}
string crudFileText = GenerateUtil.GetCRUDFileContent(tableName, csvBarcode.EnglishName, csvPrimaryKey.EnglishName);
fileDirectory = AppDomain.CurrentDomain.BaseDirectory + @"AutoGenerateCodes\CRUD";
filePath = Path.Combine(fileDirectory, $"CRUD_{tableName}.cs");
FileContentUtil.CreateFile(filePath, crudFileText, Encoding.UTF8);
DisplayInfo($"自动生成CRUD类【CRUD_{tableName}】成功.CRUD操作类路径:{filePath}");
//自动生成【编辑】窗体:添加、更新
string formDesignerText = GenerateUtil.GetFormDesignerContent(tableName);
fileDirectory = AppDomain.CurrentDomain.BaseDirectory + @"AutoGenerateCodes\Forms";
filePath = Path.Combine(fileDirectory, $"Frm{tableName}Edit.Designer.cs");
FileContentUtil.CreateFile(filePath, formDesignerText, Encoding.UTF8);
DisplayInfo($"自动生成窗体【设计器】类【Frm{tableName}Edit】成功.窗体编辑类路径:{filePath}");
string formMainText = GenerateUtil.GetFormMainContent(tableName, csvPrimaryKey.EnglishName);
filePath = Path.Combine(fileDirectory, $"Frm{tableName}Edit.cs");
FileContentUtil.CreateFile(filePath, formMainText, Encoding.UTF8);
DisplayInfo($"自动生成窗体类【Frm{tableName}Edit】成功.窗体编辑类路径:{filePath}");
//自动生成【列表】窗体:查询、删除
string listDesignerText = GenerateUtil.GetListFormDesignerContent(tableName);
filePath = Path.Combine(fileDirectory, $"Frm{tableName}List.Designer.cs");
FileContentUtil.CreateFile(filePath, listDesignerText, Encoding.UTF8);
DisplayInfo($"自动生成窗体【设计器】类【Frm{tableName}List】成功.窗体列表类路径:{filePath}");
string listMainText = GenerateUtil.GetListFormMainContent(tableName, csvBarcode.EnglishName, csvPrimaryKey.EnglishName);
filePath = Path.Combine(fileDirectory, $"Frm{tableName}List.cs");
FileContentUtil.CreateFile(filePath, listMainText, Encoding.UTF8);
DisplayInfo($"自动生成窗体类【Frm{tableName}List】成功.窗体列表类路径:{filePath}");
}
}
private void FormGenerateClass_Load(object sender, EventArgs e)
{
string sqlAllTables = "SELECT TABLE_SCHEMA,TABLE_NAME,TABLE_TYPE,CREATE_TIME,TABLE_COMMENT FROM information_schema.`TABLES` where TABLE_SCHEMA = (select database())";
DataTable dataTable = RawSql.GetDataTable(sqlAllTables, null);
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = dataTable;
cboTable.DataSource = bindingSource;
cboTable.ValueMember = "TABLE_NAME";
cboTable.DisplayMember = "TABLE_COMMENT";
}
/// <summary>
/// 显示文本框的消息
/// </summary>
/// <param name="message"></param>
private void DisplayInfo(string message)
{
this.BeginInvoke(new Action(() =>
{
if (rtxbResult.TextLength >= 20480)
{
rtxbResult.Clear();
}
rtxbResult.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} --> {message}\n");
rtxbResult.ScrollToCaret();
}));
}
private void btnTest_Click(object sender, EventArgs e)
{
string sheetName = Convert.ToString(cboTable.SelectedValue);
switch (sheetName)
{
case "input_output_log":
AutoGenerateForm.Forms.Frminput_output_logList listForm1 = new AutoGenerateForm.Forms.Frminput_output_logList(sheetName);
listForm1.Show();
break;
case "input_output_msg":
AutoGenerateForm.Forms.Frminput_output_msgList listForm2 = new AutoGenerateForm.Forms.Frminput_output_msgList(sheetName);
listForm2.Show();
break;
case "pallet_bind_pack":
AutoGenerateForm.Forms.Frmpallet_bind_packList listForm3 = new AutoGenerateForm.Forms.Frmpallet_bind_packList(sheetName);
listForm3.Show();
break;
}
}
}
}
程序运行如图:
将自动生成的,在应用程序目录下:AutoGenerateCodes目录下的CRUD、Forms、Models的三个目录及文件放在 AutoGenerateForm应用程序下。
点击”测试“按钮: