花费了十天时间,为公司开发了一套简单的网络版的信息管理系统,功能主要有客户信息管理,员工信息管理,常用信息管理(各种信函打印、常用网址/常用电话等),公司简单的财务管理等。把一些点点滴滴的技巧在此记录下来,以备查用。
1.数据绑定。 DataReader 读取数据,用DataTable.Load(IDataReader)方法将数据加载到 DataTable ,用DataGridView 显示输出。不要把DataGridView直接绑定到DataReader的目的是数据导出到Excel时,数据源可以再次从DataGridView获得。
不要在 DataGridView 内编辑添加数据,因为数据类型检查不严格(或要严格检查类型需要花费更大的成本)。
2.数据导出到 Excel 。代码如下:
/**/
/**/
/**/
/// <summary>
///
/// ** DataTable 数据导出到 Excel **
///
/// Author: 周振兴 (Zxjay 飘遥)
///
/// E-Mail: tda7264@163.com
///
/// Blog: http://blog.csdn.net/zxjay
///
/// Date: 07-08-31
///
/// </summary>
Excel.Application app
=
new
Excel.Application();
app.Visible
=
false
;
Excel.Workbook wb
=
app.Workbooks.Add(
true
);
Excel.Worksheet ws
=
(Excel.Worksheet)wb.Worksheets.Add(Type.Missing, Type.Missing, Type.Missing,
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
Type.Missing);
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
DataTable dt
=
(DataTable)dgvClientInfo.DataSource;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
for
(
int
i
=
0
; i
<
dt.Columns.Count; i
++
)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
ws.Cells[1, i + 1] = dt.Columns[i].ColumnName;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
for
(
int
j
=
0
; j
<
dt.Rows.Count; j
++
)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
for (int k = 0; k < dt.Columns.Count; k++)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
ws.Cells[j + 2, k + 1] = dt.Rows[j][k];
}
}
app.Visible
=
true
;
注意:Excel的Cells[,]下标是从1,1开始的,而不是0,0。
3.防止子窗口重复打开,确保某一子窗口只打开一次。代码为:
foreach
(Form frm
in
this
.MdiChildren)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if (frm is WorkerList)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
frm.WindowState = FormWindowState.Normal;
frm.Activate();
return;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
WorkerList wl
=
new
WorkerList();
wl.MdiParent
=
this
;
wl.Show();
4.使用枚举 enum 区分类同信息。
硬编码方式容易造成混乱。如本系统的常用电话/常用网址,数据项都为:名称-内容-备注,可将它们保存在同一个表中,在程序中为区分信息类型,可定义以下枚举:
public
enum
TelWeb
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
Telephone,WebSite
}
5.在ToolStrip中加入其它WinForm控件。
如在ToolStrip中加入DateTimePicker。如图:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/zxjay/292073/o_adddtp.png)
Code
DateTimePicker dt1 = new DateTimePicker();
dt1.Width = 110;
ToolStripControlHost host1 = new ToolStripControlHost(dt1);
host1.Alignment = ToolStripItemAlignment.Right;
toolStrip1.Items.Insert(10, host1);
6.用微软的可打印的富文本框控件打印带格式的文本。
与.NETFX自带的RichTextBox相比只增强了打印功能。通过该控件,可设置文本字体、颜色、对齐方式、粘贴图片,可打印看上去很专业的文档,截图如下:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/zxjay/292073/o_printprv1.png)
参考:http://support.microsoft.com/kb/812425/zh-cn
7.保存富文本格式到数据库。
以二进制格式保存。保存的代码为:
MemoryStream ms
=
new
MemoryStream();
rtbContent.SaveFile(ms, RichTextBoxStreamType.RichText);
byte
[] bt
=
ms.ToArray();
//
将bt保存到数据库
读取的代码为:
byte
[] bt
=
(
byte
[])SqlHelper.ExecuteScalar(sqlStr,
null
);
MemoryStream ms
=
new
MemoryStream(bt,
false
);
rtbContent.LoadFile(ms, RichTextBoxStreamType.RichText);
在SQLServer中对应的数据类型为:image
8.管理员权限控制。
管理员信息表中权限字段保存一个字符串,拥有该项权限则在字符串相应位置保存为1,没有该项权限为0。在管理员登录时判断权限,启用或禁用相应的菜单项。
9.信息分类。
如客户分类分为:软件客户、网站客户、合作客户等。如果数据量不是太大,可不用单独建立分类表,在添加的时候,客户类型。可用ComboBox,在Form加载时检索数据库中已有的客户类型填充到ComboBox中。这样可选择已有客户类型,也可以添加新的客户类型。
10.数据库安装。
不必集成在安装包中,可单独写一个WinForm程序来收集连接服务器的信息(服务器地址、数据库名、用户名、密码等),并执行数据库生成的脚本来建立数据表,视图,存储过程、索引等。
读取保存数据库脚本文件的代码:
public
static
string
ReadDBScript(
string
fileName)
{
StreamReader sr
=
new
StreamReader(fileName);
return
sr.ReadToEnd();
}
注意:数据库生成的脚本必须把"GO"去掉,否则执行时报错。
11.安全控制。
由于是网络版系统,因而安全性要考虑周全。数据库连接字符串加密保存在配置文件中。为了防止软件XCopy到其它机器中,可以取机器的硬件(如硬盘、网卡、CPU)序列号的一部分再加上自己的私有密钥作为连接字符串的加密密钥(八位ASCII),确保密钥的私密性、每机器唯一性。
(1)取得机器CPU的ID的前八位作为密钥:
public
static
string
GetProcessID()
{
try
{
string
str
=
string
.Empty;
ManagementClass mcCpu
=
new
ManagementClass(
"
win32_Processor
"
);
ManagementObjectCollection mocCpu
=
mcCpu.GetInstances();
foreach
(ManagementObject m
in
mocCpu)
{
str
=
m[
"
ProcessorId
"
].ToString().Trim().Substring(
0
,
8
);
}
return
str;
}
catch
(Exception ex)
{
return
"
zhenxing
"
;
//
如果失败取默认的密钥
}
}
(2)加密算法:
public
static
string
Encode(
string
data)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
byte[] aKey = System.Text.ASCIIEncoding.ASCII.GetBytes(GetProcessID());
byte[] aIV = System.Text.ASCIIEncoding.ASCII.GetBytes(GetProcessID());
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
DESCryptoServiceProvider cp = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, cp.CreateEncryptor(aKey, aIV), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
sw.Write(data);
sw.Flush();
cs.FlushFinalBlock();
sw.Flush();
return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
(3)解密算法:
public
static
string
Decode(
string
data)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
byte[] aKey = System.Text.ASCIIEncoding.ASCII.GetBytes(GetProcessID());
byte[] aIV = System.Text.ASCIIEncoding.ASCII.GetBytes(GetProcessID());
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
byte[] Enc;
try
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
Enc = Convert.FromBase64String(data);
}
catch
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
return null;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
DESCryptoServiceProvider cp = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream(Enc);
CryptoStream cs = new CryptoStream(ms, cp.CreateDecryptor(aKey, aIV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
return sr.ReadToEnd();
}
(4)数据库连接字符串保存到配置文件:
public
static
void
SaveToConfig(
string
connStr)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
XmlDocument doc = new XmlDocument();
string fn = "zxjay.exe.config";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
doc.Load(fn);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
XmlNodeList nodes = doc.GetElementsByTagName("add");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
for (int i = 0; i < nodes.Count; i++)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
XmlAttribute att = nodes[i].Attributes["key"];
if (att.Value == "SQLConectionString")
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/dot.gif)
{
att = nodes[i].Attributes["value"];
att.Value = connStr;
break;
}
}
doc.Save(fn);
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zxjay/archive/2007/08/31/1766329.aspx