手工制造《不完美WinForm导出Word》---同样求教高手

dingyongyuan21 2012-05-14 03:06:41
这几天公司师兄喊我做个小东西,他提供TreeView和DataTable数据源,让我写可以把数据导出到Word的功能,其中,TreeView作为表头,即列名。DataTable作为具体表的数据;TreeView如果节点下面还有子节点的话,就要在Word中分离单元格,实现如图那种列名。小弟也不是高手,在网上找了很久。。没有关于这方面的东西。。有也不全面。。而且功能也不太行。。于是我话费了一天多的时间根据网上找的Word操作和自己以测试心态写的代码。。。竟然成功了。。。

但是师兄还让我在Word中写目录。。这个我暂时没什么思路。。。就先把自己的代码共享下。。希望帮到你们。。里面的那个for循环我话费了一下午+两小时才搞定的。。太他妈的绕了。。。

注意:这段代码可以运行,但dataTable的列名必须和TreeView节点+子节点的个数一样。。。不然就会报错。。ToWord()里面可以给自己写的TreeView对象,也可以给TreeView控件(可以把上面手动添加TreeView代码复制到加载事件里,为TreeView提供数据),只要dataTable的列名和TreeView节点+子节点的个数一样就OK。。。CSDN里面怎么给图片。。。这个我不知道。。。感兴趣的自己导出去看下。。。同时也求教高手。。。导出目录有什么思路提供没。。。QQ:619870447 欢迎指教

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


namespace Word导出
{
/// <summary>
///word导出
///编写人:
///日期:2012-5-5
/// </summary>
public partial class ToWord : Form
{

public ToWord()
{
InitializeComponent();
}
/// <summary>
/// 导出文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnDC_Click(object sender, EventArgs e)
{

//手动添加DataTable数据
DataTable tb = new DataTable();
//手动添加列数据
tb.Columns.Add("姓名");
tb.Columns.Add("喜欢");
tb.Columns.Add("讨厌");
tb.Columns.Add("农历");
tb.Columns.Add("阳历");
tb.Columns.Add("身高");
tb.Columns.Add("体重");
tb.Columns.Add("性别");
//手动添加行数据
tb.Rows.Add("***", "女人", "男人", "1992-11-18", "1992-12-11", "171cm","65kg", "男");
tb.Rows.Add("***", "女人", "男人", "1992-11-18", "1992-12-11", "171cm", "65kg", "男");
tb.Rows.Add("***", "女人", "男人", "1992-11-18", "1992-12-11", "171cm", "65kg", "男");
tb.Rows.Add("***", "女人", "男人", "1992-11-18", "1992-12-11", "171cm", "65kg", "男");

//手动添加TreeView数据
TreeNode tn = new TreeNode();
tn.Text = "姓名";

TreeNode tn2 = new TreeNode();
tn2.Text = "兴趣";
TreeNode tn21 = new TreeNode();
tn21.Text = "喜欢";
TreeNode tn22 = new TreeNode();
tn22.Text = "讨厌";
tn2.Nodes.Add(tn21);
tn2.Nodes.Add(tn22);

TreeNode tn3 = new TreeNode();
tn3.Text = "生日";
TreeNode tn31 = new TreeNode();
tn31.Text = "农历";
TreeNode tn32 = new TreeNode();
tn32.Text = "阳历";
tn3.Nodes.Add(tn31);
tn3.Nodes.Add(tn32);

TreeNode tn4 = new TreeNode();
tn4.Text = "身高";
TreeNode tn41 = new TreeNode();
tn41.Text = "身高";
TreeNode tn42 = new TreeNode();
tn42.Text = "体重";

TreeNode tn5 = new TreeNode();
tn5.Text = "性别";

TreeView tv = new TreeView();
tv.Nodes.Add(tn);
tv.Nodes.Add(tn2);
tv.Nodes.Add(tn3);
tv.Nodes.Add(tn4);
tv.Nodes.Add(tn5);

SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Word文档(*.doc)|*.doc";
if (sfd.ShowDialog() == DialogResult.OK)
{
DataTableToWord(tb, sfd.FileName,treeView1);
}
}

/// <summary>
/// 操作word
/// </summary>
/// <param name="dt">dataTable数据源</param>
/// <param name="tv">TreeView数据源</param>
/// <param name="fileName">保存地址</param>
public void DataTableToWord(DataTable dt, string fileName,TreeView tv)
{

Object Nothing = System.Reflection.Missing.Value;
object filename = fileName;//文件保存路径
Word.Application WordApp = new Word.ApplicationClass();
//创建一个文档
Word.Document WordDoc = WordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);



//获取创建表格列数
int Num = tv.Nodes.Count;
int notNull = 0;
for (int i = 0; i < tv.Nodes.Count; i++)
{
if (tv.Nodes[i].Nodes.Count != 0)
{
Num = Num + tv.Nodes[i].Nodes.Count;
notNull = notNull + 1;
}
}
//文档中创建表格,其中的第2和3个参数是创建的表格的行数和列数,给的值是dataTable的行数和列数
Word.Table newTable = WordDoc.Tables.Add(WordApp.Selection.Range, dt.Rows.Count + 1, Num - notNull, ref Nothing, ref Nothing);

//表格的外线格式
//newTable.Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleEngrave3D;
//////表格的内线格式
//newTable.Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleNone;


//将原数据导入到新建的表中
//i代表行数,j代表列
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < Num - notNull; j++)
{
newTable.Cell(i+2, j + 1).Range.Text = Convert.ToString(dt.Rows[i][j]);//循环输出单元格内容
}
}

#region 分离头部单元格代码实现
//循环TreeView索引,获取子节点不为空的节点索引
for (int a = 0; a < tv.Nodes.Count; a++)//a代表节点索引
{
if (tv.Nodes[a].Nodes.Count != 0)//判断节点的子节点是否为空,不为空获取子节点count和Index
{
//当节点下子节点不为空时,对该节点进行循环操作
for (int i = 0; i < tv.Nodes.Count; i++)//i代表列,tv.Nodes.count = 列数;
{
if (i == a)//当列数等于不为空节点索引时
{
//循环行
for (int j = 1; j <= newTable.Rows.Count; j++)//j代表行;
{
if (j == 1)//当行数等于1时(就是需要分离的头部列名单元格)
{

//分离表头单元格,2行两列
object RowNum = 2;
object ColumNum = tv.Nodes[a].Nodes.Count;
Word.Cell cell = newTable.Cell(j, i + 1);
//先合并多出来的单元格
cell.Merge(newTable.Cell(j, i + 2));
//按照子节点个数分离合并后的单元格
cell.Split(ref RowNum, ref ColumNum);
//合并头部第一行,第二行不合并
cell.Merge(newTable.Cell(j, i + 2));
//循环为头部分离单元格循环赋值
for (int d = 0; d < tv.Nodes[a].Nodes.Count; d++)//d代表节点下子节点索引
{
//循环赋值
newTable.Cell(j + 1, i + d + a).Range.Text = tv.Nodes[a].Nodes[d].Text;
}
}
}
}
}
}
}
#endregion

//循环出第一行列名
for (int i = 0; i < tv.Nodes.Count; i++)
{
newTable.Cell(1, i + 1).Range.Text = tv.Nodes[i].Text;
}

newTable.Range.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;//整个表格文本居中




#region 设置最后一行
//加一行 最后
newTable.Rows.Add(ref Nothing);

//最后一行所有单元格合并,并设置文本
Word.Cell cell2 = newTable.Cell(dt.Rows.Count + 3, 1);
cell2.Merge(newTable.Cell(dt.Rows.Count + 3, Num - notNull));
newTable.Cell(dt.Rows.Count + 3, 1).Range.Text = "文档创建时间:" + DateTime.Now;
//文本居右
newTable.Cell(dt.Rows.Count + 3, 1).Range.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphRight;//设定单独行文本居左
#endregion


#region 保存文档并退出
//保存word文档
WordDoc.SaveAs(ref filename, ref Nothing, ref Nothing,
ref Nothing, ref Nothing, ref Nothing, ref Nothing,
ref Nothing, ref Nothing, ref Nothing, ref Nothing,
ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);

MessageBox.Show("文档导出成功!","提示框",MessageBoxButtons.OK,MessageBoxIcon.Information);


//关闭并退出进程

WordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
WordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
#endregion
}
/// <summary>
/// 关闭
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}

/// <summary>
/// 加载
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ToWord_Load(object sender, EventArgs e)
{
//把上面代码复制到这里就OK

treeView1.Nodes.Add(tn);
treeView1.Nodes.Add(tn2);
treeView1.Nodes.Add(tn3);
treeView1.Nodes.Add(tn4);
treeView1.Nodes.Add(tn5);

//this.treeView1.ContrControlsls.Add(tv);
}

}
}
...全文
167 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
dingyongyuan21 2012-11-20
  • 打赏
  • 举报
回复
dingyongyuan21 2012-11-12
  • 打赏
  • 举报
回复
引用 3 楼 xuezhongshengai 的回复:
顶一个 编程习惯很好 注释和代码都很规范 代码可读性很强 学习了
sankeyou
xuezhongshengai 2012-11-11
  • 打赏
  • 举报
回复
顶一个 编程习惯很好 注释和代码都很规范 代码可读性很强 学习了
dingyongyuan21 2012-11-05
  • 打赏
  • 举报
回复
为毛没人来顶?
dingyongyuan21 2012-05-14
  • 打赏
  • 举报
回复
自己先顶。。。不然直接沉了想哭都来不及

17,740

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 .NET Framework
社区管理员
  • .NET Framework社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧