前段时间,受命写出一个把客户提交的的电子数据资料(大部份是excel,也可以是word,access等)转成标准的SQL语句。以初始化数据库,保护客户现有的资料,减轻客户的负担。原来也有过这样的转化工作,本想拿来就用,具体看了之后才发现不可能,无奈之际只有自己实现一个这样的导入设计,目标是减轻以后的导入工作。
针对客户提交资料的不规范性(这里我指的规范是从程序员的角度来看),那么我们要做的一个工作就是在原来资料的基础上增加开发的一些规范。比如说客户提交了一张个人的信息表(如下:第二行是我后来加上去),如果单看用户提交的表那么要转成SQL语句,就会出现字段对应的依懒,还有引用的依懒。而一旦出现了这样的依懒就没有通用性可言(这句话有点过了,但至少是通用性明显减弱),为此我们可以对这张表进行预处理加上一行指示与SQL中字段的对应,这样我们就摆脱了case "性别": return "Gender";break;这样的依懒了。或许有人会对此持以不同的态度,说我将程序中的这些CASE移至外层来处理,这个我接受,这一步是必不可少的,就看放在那里为优了。设计就是充满权衡的,如果没有权衡那么这个设计肯定忽略了一个弱点。这样放到外层,可以减少程序编译,降低程序复杂性等。解决了字段的对应关系,还有值的写法关系也要解决的,如字符串的和整型的值的insert语句时就不同,为些我加上了{int}来表示整型。default就是string了,当然还可以有别的类型。第三个要解决的问题是引用,在我的数据库设计中是基础资料项及类共用的是三张表,所以这里就会出现
Party:EntryItem(Party){int},表时在这个Entryitem表中的项必须是party这种类别。一般的不放在一张表的就写成如下的形式Congress:Congress{int}就好了,这样就完成在外围解决引用这个问题。在上面我完成外部数据的无二义表示,对其它格式的文件都可以采用上似类似做法来完成数据适应过程。
姓名 |
性别 |
出生日期 |
民族 |
藉贯 |
党派 |
学历 |
边界 |
是否归侨 |
选区 |
工作单位及职务 |
职位 |
工作地址 |
电话 |
工作地址邮编 |
家庭地址 |
家庭电话 |
家庭邮编 |
联系方式 |
可否交换 |
手机 |
可否公布手机 |
|
秘书姓名 |
秘书电话 |
专业小组 |
是否选择 |
代表届期 |
是否常委 |
代表证号 |
证号简码 |
技能特长 |
任职类别 |
描述 |
相片 |
Name |
Gender:EntryItem(Gender){int} |
Birthday |
Nationality:EntryItem(Nationality){int} |
Nativeplace |
Party:EntryItem(Party){int} |
Education:EntryItem(Education){int} |
Boundary:EntryItem(Boundary){int} |
IsROC{int} |
ElectoralDistrict:EntryItem(ElectoralDistrict){int} |
Organization |
Position |
Address |
OfficeTelephone |
OfficePostCode |
HomeAddress |
HomeTelephone |
HomePostCode |
ContactType:EntryItem(ContactType){int} |
CanSwitch{int} |
Mobile |
CanPublicMobile{int} |
Email |
SecretaryName |
SecretaryTelephone |
SpecialGroup |
IsSelected{int} |
Congress:Congress{int} |
IsPermanent |
CertificateNo |
CertificateSimpleNo |
Technology |
ElectionType:EntryItem(ElectionType) |
Description |
Photo |
AAA |
男 |
|
汉 |
|
共产党 |
未知 |
未知 |
0 |
天沙 |
AAA公司 |
董事、总经理 |
|
|
|
|
|
|
|
0 |
|
0 |
|
|
|
|
0 |
|
0 |
|
1 |
|
现任 |
|
|
由于客户提供的电子数据多样性,我就决定先生成XML然后由XML去生成SQL,这样就可以独立出XML生成SQL这一块。到时用XML生成别的什么形式都是可以的。代码如下:这里读取excel我用了Syncfusion。生成后的XML应是这样的形式
<?xml version="1.0"?>
<table name="...">
<record id="1">
<property name="name" value="AAA"/>
......
</record>
.....
</table>
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Xml;
5using System.IO;
6using Syncfusion.XlsIO;
7
8namespace EntitiesTest.Xml
9{
10 static class XmlConstraint
11 {
12 public const string TABLE = "table";
13 public const string RECORD = "record";
14 public const string PROPERTY = "property";
15 public const string NAME = "name";
16 public const string REFRENCE = "Refrence";
17 public const string RESTRICT = "Restrict";
18 public const string VALUE = "value";
19 public const string ID = "Id";
20 public const string TYPE = "Type";
21
22 //类型
23 public const string INT = "int";
24 public const string STRING = "string";
25 }
26
27 class HeaderInformation
28 {
29 private string _HeaderName;
30 public string HeaderName
31 {
32 get { return _HeaderName; }
33 }
34
35 private string _ColumnRefrence;
36 public string ColumnRefrence
37 {
38 get { return _ColumnRefrence; }
39 }
40
41 private string _Restrict;
42 public string Restrict
43 {
44 get { return _Restrict; }
45 }
46
47 private string _DataType;
48 public string DataType
49 {
50 get { return _DataType; }
51 }
52
53 public HeaderInformation(string name)
54 :this(name,string.Empty)
55 {
56 }
57
58 public HeaderInformation(string name, string refrence)
59 : this(name,refrence,string.Empty)
60 {
61 }
62
63 public HeaderInformation(string name, string refrence, string restrict)
64 {
65 }
66 public HeaderInformation(string name, string refrence, string restrict,string strType)
67 {
68 _HeaderName = name;
69 _ColumnRefrence = refrence;
70 _Restrict = restrict;
71 _DataType = strType;
72 }
73 }
74
75 struct ColumnInformation
76 {
77 private string _Value;
78 private HeaderInformation _HeaderInformation;
79
80 public ColumnInformation(HeaderInformation headerInformation, string strValue)
81 {
82 _HeaderInformation = headerInformation;
83 _Value = strValue;
84 }
85
86 public void Convert(XmlWriter writer)
87 {
88 writer.WriteStartElement(XmlConstraint.PROPERTY);
89 writer.WriteAttributeString(XmlConstraint.NAME, _HeaderInformation.HeaderName);
90 writer.WriteAttributeString(XmlConstraint.VALUE, _Value);
91 writer.WriteAttributeString(XmlConstraint.TYPE, _HeaderInformation.DataType);
92 if (!string.IsNullOrEmpty(_HeaderInformation.ColumnRefrence))
93 {
94 writer.WriteAttributeString(XmlConstraint.REFRENCE, _HeaderInformation.ColumnRefrence);
95 if (!string.IsNullOrEmpty(_HeaderInformation.Restrict))
96 {
97 writer.WriteAttributeString(XmlConstraint.RESTRICT, _HeaderInformation.Restrict);
98 }
99 }
100 writer.WriteEndElement();
101 }
102 }
103
104 class RowInformation
105 {
106 private int _Id;
107 private List<ColumnInformation> columnList = new List<ColumnInformation>();
108
109 public RowInformation(int Id)
110 {
111 _Id = Id;
112 }
113
114 public void AddColumn(ColumnInformation column)
115 {
116 columnList.Add(column);
117 }
118
119 public void Convert(XmlWriter writer)
120 {
121 writer.WriteStartElement(XmlConstraint.RECORD);
122 writer.WriteAttributeString(XmlConstraint.ID, _Id.ToString());
123 foreach (ColumnInformation column in columnList)
124 {
125 column.Convert(writer);
126 }
127 writer.WriteFullEndElement();
128 }
129 }
130
131 public class XlsTableXml
132 {
133 private IWorksheet _WorkSheet;
134 protected IWorksheet WorkSheet
135 {
136 get { return _WorkSheet; }
137 }
138
139 private int _RowTitle = 0;
140 public int RowTitle
141 {
142 get { return _RowTitle; }
143 set { _RowTitle = value; }
144 }
145
146 private int _Columns;
147 public int Columns
148 {
149 get { return _Columns; }
150 set { _Columns = value; }
151 }
152
153 private string _FilePath;
154 public string FilePath
155 {
156 get { return _FilePath; }
157 set { _FilePath = value; }
158 }
159
160 public XlsTableXml(IWorksheet sheet)
161 {
162 _WorkSheet = sheet;
163 }
164
165 private Dictionary<int, HeaderInformation> _HeaderDict = new Dictionary<int, HeaderInformation>();
166 public void ConvertToXml()
167 {
168 if (Columns == 0)
169 {
170 _Columns = 100;
171 }
172 if (string.IsNullOrEmpty(_FilePath))
173 {
174 throw new InvalidOperationException("没有为路径赋值");
175 }
176 string strFullPathName = _FilePath + "\\" + WorkSheet.Name + ".xml";
177 CreateXmlFile(strFullPathName);
178 //建立写对象
179 XmlWriterSettings setting = new XmlWriterSettings();
180 setting.Indent = true;
181 setting.OmitXmlDeclaration = false;
182 setting.NewLineOnAttributes = false;
183 XmlWriter writer = XmlWriter.Create(strFullPathName,setting);
184 CollectHeaderInformation();
185 int iCurrent=_RowTitle+1;
186 //写动作
187 writer.WriteStartElement(XmlConstraint.TABLE);
188 writer.WriteAttributeString(XmlConstraint.NAME, WorkSheet.Name);
189 for (int iRow = iCurrent; iRow < WorkSheet.Rows.Length; ++iRow)
190 {
191 IRange row = WorkSheet.Rows[iRow];
192 RowInformation rowInfo = new RowInformation(iRow);
193 for (int iColumn = 0; iColumn < _HeaderDict.Count; ++iColumn)
194 {
195 string strValue = row.Cells[iColumn].Value.Trim();
196 if (!string.IsNullOrEmpty(strValue))
197 {
198 ColumnInformation column = new ColumnInformation(_HeaderDict[iColumn], strValue);
199 rowInfo.AddColumn(column);
200 }
201 }
202 rowInfo.Convert(writer);
203 }
204 writer.WriteFullEndElement();
205 writer.Flush();
206 }
207
208 private void CollectHeaderInformation()
209 {
210 for (int iColumn = 1; iColumn < Columns; ++iColumn)
211 {
212 string strFullValue = WorkSheet.GetText(RowTitle+1, iColumn);
213 if (string.IsNullOrEmpty(strFullValue))
214 {
215 return;
216 }
217 HeaderInformation headerInformation = null;
218 string strRefrence = string.Empty;
219 string strRestrict = string.Empty;
220 string strName = string.Empty;
221 string strType = Xml.XmlConstraint.STRING;
222 int iLeft = strFullValue.IndexOf('{');
223 int iRight = strFullValue.IndexOf('}');
224 if (iLeft > 0 && iLeft < iRight)
225 {
226 string temp = strFullValue.Substring(iLeft + 1, iRight - iLeft - 1);
227 if (temp == XmlConstraint.INT)
228 {
229 strType = XmlConstraint.INT;
230 }
231 strFullValue = strFullValue.Substring(0, iLeft);
232 }
233 int colon = strFullValue.IndexOf(':');
234 if (colon < 0)
235 {
236 strName=strFullValue.Trim();
237 }
238 else
239 {
240 strName = strFullValue.Substring(0, colon).Trim();
241 int leftBracket = strFullValue.IndexOf('(');
242 if (leftBracket < 0)
243 {
244 strRefrence = strFullValue.Substring(colon + 1);
245 }
246 else
247 {
248 int rightBracket = strFullValue.IndexOf(')');
249 strRefrence = strFullValue.Substring(colon + 1, leftBracket - colon-1).Trim();
250 strRestrict = strFullValue.Substring(leftBracket + 1, rightBracket - leftBracket-1).Trim();
251 }
252 }
253 _HeaderDict.Add(iColumn-1,new HeaderInformation(strName,strRefrence,strRestrict,strType));
254 }
255 }
256
257 private void CreateXmlFile(string strFullPathName)
258 {
259 if (!File.Exists(strFullPathName))
260 {
261 using (File.Open(strFullPathName, FileMode.Create))
262 {
263 }
264 }
265 else
266 {
267 File.SetAttributes(strFullPathName, FileAttributes.Archive);
268 }
269 }
270 }
271}
272
1using System.Xml;
2using System.IO;
3using Syncfusion.XlsIO;
4
5namespace EntitiesTest.Xml
6{
7 public class Launch
8 {
9 private IWorkbook _Workbook;
10 public IWorkbook Workbook
11 {
12 get { return _Workbook; }
13 }
14
15 private List<string> _convertList = new List<string>();
16
17 public Launch(IWorkbook book)
18 {
19 _Workbook = book;
20 }
21
22 public void AddConvertName(string name)
23 {
24 if (!_convertList.Contains(name))
25 {
26 _convertList.Add(name);
27 }
28 }
29
30 public void Start(string strDictionary)
31 {
32 foreach (string name in _convertList)
33 {
34 IWorksheet sheet = _Workbook.Worksheets[name];
35 if (sheet == null)
36 {
37 throw new ArgumentOutOfRangeException(string.Format("{0}表没有找到,出错", name));
38 }
39 XlsTableXml xlsTable = new XlsTableXml(sheet);
40 xlsTable.RowTitle = 1;
41 xlsTable.FilePath = strDictionary;
42 xlsTable.ConvertToXml();
43 }
44 }
45 }
46}
47