前段時間,受命寫出一個把客戶提交的的電子數據資料(大部份是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>
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Xml;
5
using System.IO;
6
using Syncfusion.XlsIO;
7
8
namespace 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
1
using System.Xml;
2
using System.IO;
3
using Syncfusion.XlsIO;
4
5
namespace 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