您的位置:首页 > 编程语言 > C#

用C#操作office组件库实现word文档的创建及文字 表格 图片的插入

2016-06-20 15:02 1046 查看
最近写了一个小程序,学了不少东西,总结一下,要实现的功能是读取本地文件夹中的txt和png文件自动生成一个.docx报告文档,首先对需要解决的问题进行分解,最后组合起来。

1.打开一个本地文件夹,利用IO命名空间中的目录信息DirectoryInfo的GetFiles方法获得该目录中文件列表,然后根据扩展名判断是否同时包含txt和png文件,如果是,则将目录信息作为参数进行传递并显示在两个文本框中,以便后期操作,否则重新选择文件夹。参考博客http://www.cnblogs.com/skylaugh/archive/2012/09/23/2698850.html

private void PathBtn_Click(object sender, EventArgs e)
{
this.GenerateReportBtn.Enabled = true ;
this.toolStripStatusLabel1.Text = "正在打开文件...";

FolderBrowserDialog folderDLg = new FolderBrowserDialog();
folderDLg.Description = "打开生成报告文件目录";
string folderName;
folderDLg.ShowDialog();
folderName = folderDLg.SelectedPath;
if (folderName == "")
{
MessageBox.Show("结果目录不能为空,请选择指定目录","提示",MessageBoxButtons.OK,MessageBoxIcon.Warning);
return;
}
DirectoryInfo directory = new DirectoryInfo(folderName);
FileInfo[] filesInfo = directory.GetFiles();
int length = filesInfo.Length;
int count = 0;
foreach (FileInfo NextFile in directory.GetFiles())
{
string fileExtension = NextFile.Extension;
switch (fileExtension)
{
case ".txt":
count++;
break;
case ".png":
count++;
break;
case ".docx":
count++;
break;
}
}
if (count == length)
{
OperateWord operateWord = new OperateWord();
operateWord.FolderName = folderName;
this.WordDocTxtBox.Text = folderName;
this.DocxSaveAsTxtBox.Text = operateWord.GetWordFullName();
}
else
{
MessageBox.Show("指定文件夹中没有txt文件和png图片,请重新选择!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
this.toolStripStatusLabel1.Text = "打开文件路径成功";
}
2.打开包含txt和png文件的目录后,需要根据文件的扩展名分别将txt和png文件的文件名和目录信息存放在四个字符串数组中,以便后期使用,这一步需要解决两个问题:一是统计字符串中某个字符出现的次数,并去掉不符合要求的txt文件;二是需要对含有数字的的字符串根据数字进行排序。参考博客http://q.cnblogs.com/q/54877/  和http://q.cnblogs.com/q/54877/ 

DirectoryInfo directory = new DirectoryInfo(folderName);
List<string> txtList = new List<string>();
List<string> pngList = new List<string>();
List<string> txtListPath = new List<string>();
List<string> pngListPath = new List<string>();
foreach (FileInfo NextFile in directory.GetFiles())
{
string fileExtension = NextFile.Extension;
switch (fileExtension)
{
case ".txt":
int count = NextFile.Name.Length - NextFile.Name.Replace("_", "").Length;//统计下划线出现的次数,去掉不符合条件的txt文件
if (count == 1)
{
txtList.Add(NextFile.Name);
txtListPath.Add(NextFile.FullName);
}
break;
case ".png":
pngList.Add(NextFile.Name);
pngListPath.Add(NextFile.FullName);
break;
}
}
IComparer<string> txtFileNamesComparer = new TxtFileNamesComparer();//自定义比较器—根据字符串中的数字进行从大到小的排序
txtList.Sort(txtFileNamesComparer);//按第一个下划线前的数字给文件名排序
//txt和png文件名,txt文件名按第一个下划线之前的数字排序
txtFileNames = new string[txtList.Count];
txtFileNames = txtList.ToArray();
pngFileNames = new string[pngList.Count];
pngFileNames = pngList.ToArray();

//txt和png的完整路径
txtFilePaths = new string[txtListPath.Count];
txtFilePaths = txtListPath.ToArray();
pngFilePaths = new string[pngListPath.Count];
pngFilePaths = pngListPath.ToArray();

自定义比较器:

public class TxtFileNamesComparer:IComparer<string>
{
/// <summary>
/// 按文件名中的数字给文件名排序
/// </summary>
/// <param name="x">文件名1</param>
/// <param name="y">文件名2</param>
/// <returns></returns>
public int Compare(string x, string y)
{
if (x == string.Empty || y == string.Empty)
throw new ArgumentException("Parameters can't be null");
string subX = x.Substring(0, x.IndexOf("_"));
string subY = y.Substring(0, y.IndexOf("_"));
int result = 0;
if (int.Parse(subX) > int.Parse(subY))
{
result = 1;
}
if (int.Parse(subX) < int.Parse(subY))
{
result = -1;
}
if (int.Parse(subX) == int.Parse(subY))
{
result = 0;
}
return result;
}
}
3.根据程序运行目录中包含的类型编号txt文件替换表格中的编号

public void ReplaceClass(ref string classID)
{
//获取应用程序运行目录
string FeatureClassPath = Application.StartupPath.ToString() + "\\Classes\\Class.txt";
//string[] classlines = File.ReadAllLines(FeatureClassPath, Encoding.GetEncoding("gb2312"));//读取汉字
string[] classlines = { };
List<string> LinesListt = new List<string>(classlines);
IEnumerable<string> stt = File.ReadLines(FeatureClassPath, Encoding.GetEncoding("gb2312"));//txtPath="C:\\Users\\john\\Desktop\\report\\N2_N3.txt"
LinesListt.AddRange(stt);//将所有txt放在LineList泛型中
LinesListt.RemoveAt(classlines.Length);//删除每个txt文件的第一行
classlines = LinesListt.ToArray();//将泛型转换为字符串数组 将所有的txt文件中的数据除去第一行后全部放在string数组中
foreach (string item in classlines)
{
string[] strs = item.Split('\t');//根据制表符分隔字符串
if (strs[0] == classID)
{
classID = strs[1];
}
}
}4.根据有序字符串数组中的txt文件名获取默认的word文档的名称——第一个文件名的第一个数字+最后一个文件名的第二个数字的组合
//获取word文档的完整保存路径和名称
public string DocxPathInfo()
{
string docxPathInfo = folderName;
string docxName = string.Empty;
string strStart = txtFileNames[0].Substring(0, txtFileNames[0].IndexOf("_"));//第一个文件名的第一个数字
string strEnd = txtFileNames[txtFileNames.Length - 1].Substring(txtFileNames[txtFileNames.Length - 1].IndexOf("_"), txtFileNames[txtFileNames.Length - 1].IndexOf(".") - txtFileNames[txtFileNames.Length - 1].IndexOf("_"));//最后一个文件名的第二个数字
docxName ="\\"+ strStart + strEnd+".docx";
docxPathInfo += docxName;
return docxPathInfo;
}5.创建word文档、插入文字、表格和图片,一个非常重要的变量object EndOfDoc = "\\endofdoc";定位到文档末尾
创建word文档

wordApp = new MSWord.ApplicationClass();//创建应用程序对象
wordDoc = wordApp.Documents.Add(ref nothing, ref nothing, ref nothing, ref nothing);//创建word文档插入文字
wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;//设置字体居中
wordApp.Selection.Font.Size = 23;//设置字体大小
wordApp.Selection.Font.Bold = 2;//设置加粗, 不加粗为0
wordApp.Selection.Font.Name = "黑体 ";//设置字体为黑体
wordApp.Selection.TypeText("\nXXXXXX\n");插入表格
MSWord.Range range = wordApp.Selection.Range;
//插入表格
MSWord.Table table = wordDoc.Tables.Add(range, tableRow+1, tableColumn, ref nothing, ref TabAutoFit);
table.Borders.Enable = 1;//默认表格没有边框
for (int row = 2; row <= tableRow + 1; row++)//=
{
for (int column = 1; column <= tableColumn; column++)
{
//table.Cell(row, column).Range.Text = "(" + row + "行" + "," + column + "列";
table.Cell(row, column).Range.Font.Size = 8;
table.Cell(row, column).Range.Bold = 0;
table.Cell(row, column).Range.Font.Name = "宋体";
table.Cell(row, column).Range.Text = tableData[row - 2, column - 1].ToString();
}
}
插入图片(根据txt文件名插图对应名称的png图片)
for (int i = 0; i < txtFilePaths.Length; i++)
{
//txtFileNames[i] = txtFilePaths[i].Substring(txtFilePaths[i].LastIndexOf("\\") + 1);
int subTabRows = 0, subTabColumn = 0;
string[] lines = File.ReadAllLines(txtFilePaths[i]);
List<string> LinesList = new List<string>(lines);
LinesList.RemoveAt(0);
lines = LinesList.ToArray();
if (lines[lines.Length - 1] == "")
{
subTabRows = lines.Length - 1;//消除最后一行空行
}
else
{
subTabRows = lines.Length;
}
string[,] datas = new string[subTabRows, 10];//按照行列读取文本文件 这个地方需要动态增加字符串
int m = 0;
foreach (string line in lines)
{
string[] str = line.Split('\t');
string[] strColsDat = new string[str.Length + 1];//增加序号列
for (int j = 1; j < strColsDat.Length; j++)
{
strColsDat[0] = (m + 1).ToString();
strColsDat[j] = str[j - 1];

}
for (subTabColumn = 0; subTabColumn < strColsDat.Length; subTabColumn++)
{
if (subTabColumn == 5)
{
txtPngInfo.ReplaceClass(ref strColsDat[subTabColumn]);
}
datas[m, subTabColumn] = strColsDat[subTabColumn];
}
m++;
}
MSWord.Range range3 = wordDoc.Bookmarks.get_Item(ref EndOfDoc).Range;//标签定位
CreateSubTable(range3, subTabRows + 1, subTabColumn, datas);//创建子表格,创建时可以设置子表格行数,可以根据txt中的杆塔区间名称出现的次数确定子表格行数

//根据txt文件名插入对应名称的图片
for (; index < pictureNames.Length; index++)
{

if (pictureNames[index].Substring(0, pictureNames[index].IndexOf('.') - 2) == txtFileNames[i].Substring(0, txtFileNames[i].IndexOf('.')))
{
InsertPicture(picturePaths[index]);//插入俯视图和侧视图
}
else
{
break;
}
}
}
private static void InsertPicture(string picturePath)
{
// wordDoc.Paragraphs.Last.Range.Text = "\n";//换行
//插入图片
//             object wordLine = MSWord.WdUnits.wdLine;
//             object count = 3;
//             wordApp.Selection.MoveDown(ref wordLine, count, nothing);//test30\2.doc
//            wordApp.Selection.TypeParagraph();//插入段落  80//test30\3.doc
object LinkOfFile = false;
object SaveDocument = true;
//object range = wordApp.Selection.Range;
object range3 = wordDoc.Bookmarks.get_Item(ref EndOfDoc).Range;
wordDoc.InlineShapes.AddPicture(picturePath, ref LinkOfFile, ref SaveDocument, ref range3);

}
6.根据指定的路径或者默认路径保存生成的word文档,并退出word文档的编辑
public static void SaveAsWordDocument(string filepath)
{
object wordPath = null;
object format = MSWord.WdSaveFormat.wdFormatDocumentDefault;//设置保存格式为.docx
wordPath = filepath;
if (wordPath == null)
{
throw new ArgumentException("报告路径不能为空!");
}
if (File.Exists((string)wordPath))
{
File.Delete((string)wordPath);
}
wordDoc.SaveAs2(wordPath, ref format, ref nothing, ref nothing, ref nothing, ref nothing, ref nothing);//保存创建的word文档
wordDoc.Close(ref nothing, ref nothing, ref nothing);//关闭word文档
wordApp.Quit(ref nothing, ref nothing, ref nothing);//退出word文档
}7.调用时间函数实现进度条
[DllImport("winmm.dll")]
protected static extern int timeGetTime();
int startTime = timeGetTime();
//this.progressBar1.Step = startTime + 1;
this.toolStripProgressBar1.Step = startTime + 1;
this.toolStripProgressBar1.PerformStep();
8.暂停几秒后隐藏进度条
{
this.timer1.Interval = 1500;//报告生成成功后,暂停几秒后,隐藏进度条
this.timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
this.toolStripProgressBar1.Visible = false;//暂停几秒后,隐藏进度条
this.timer1.Enabled = true;
}

以上是这次写程序时,遇到的一些问题。

菜鸟的总结,关键是以后自己再用到的时候会比较方便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: