非常舒服的操作,唯一令人讨厌的问题是目标文件的行列长宽不能修改,希望有大神帮忙修改代码(已经可以更改了)
更新:如果要把它部署到服务器上一定要注意蛋疼的几点。
首先要注意,服务器上必须装有excel,而且excel版本最好与测试环境下的一样,否则鬼才知道会出什么bug(不过我的测试环境是2010,服务器上是2013倒是没出错,但还是要注意一下版本的问题);
其次,要在组件服务(dcomcnfg.exe)里面进行设置,否则会报没有权限禁止访问的问题。找到excel的组件服务,我这里是Microsoft Excel Application,选择属性,点击“安全”选项卡,把启动和激活权限设为自定义,然后选择编辑,选择添加,因为我手里用的是IIS服务器,所以我这边需要加入IIS_IUSRS用户,网上说是要加入NETWORK SERVICE用户,但是我这边是要加入IIS_IUSRS用户,初步推测是使用的服务器不同,但鬼知道是什么情况呢,在IIS_IUSRS的权限下加入本地启动和本地激活,如果需要NETWORK SERVICE的话也一样,然后在访问权限下也做类似的设置,把上述用户添加进去,并添加本地访问的权限;
再次,我这边尝试连接服务器调用带格式复制的方法时出现了“
因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码
”的问题,我的解决方法是在excel的组件服务里选择标识选项卡,勾选为下列用户(网上一般说配置的时候要选择交互式用户,我这边是失败的),然后把当前登录到服务器的用户名和密码输入保存即可;
还有 ,有时候可能会出现excel程序无法正常退出的情况,强烈建议在调用完方法之后进行一次GC.Collect()。
更新:在把本程序部署到服务器上后,出现了无法复制的情况,原因是程序创建的xls文件为只读的xls文件,所以无法写入,解决方法是将网站所在的文件夹增加一个IIS_IUSRS用户
//引入Microsoft.Office.Interop.Excel.dll(找不到Microsoft.Office.Interop.Excel.dll的话可以参考我的另一篇文章解决无法找到Microsoft.Office.Interop.Excel并将其分离的方法)也可以直接引用excel.exe
using Microsoft.Office.Interop.Excel;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class ExcelCopy
{
/// <summary>
/// 将源excel复制到目标excel
/// </summary>
/// <param name="copyfilePosition">需复制文件的路径以及文件名</param>
/// <param name="targetPosition">目标文件路径以及文件名</param>
public void fakCopy(string copyfilePosition, string targetPosition)
{
Application app = new Application();
//app.Visible = false;更新:这一条数据不要加上,会出现无法复制的问题,奇怪的是如果我加上了这句话,我在上一句设断点然后执行就会报错,直接运行却不一定会有问题,把这条注释掉就可以解决这个问题,搞不懂微软在干什么
app.DisplayAlerts = false;
object missing = System.Reflection.Missing.Value;
Workbook tarFileWk;
Worksheet cpFileSh;
try
{
Workbook cpFileWk = app.Workbooks.Open(copyfilePosition);//需复制文件位置
tarFileWk = app.Workbooks.Open(targetPosition);//目标文件位置
//Console.WriteLine(copyfilePosition);
Worksheet sheets = (Worksheet)cpFileWk.Sheets[1];
string sheetName = sheets.Name; //Sheet名
cpFileSh = (Worksheet)cpFileWk.Worksheets[sheetName];
int row = cpFileSh.UsedRange.Cells.Rows.Count;//获取最大行数
int column = cpFileSh.UsedRange.Cells.Columns.Count;//获取最大列数
string letterCol = ExcelCopy.ToNumberSystem26(column);//把最大列数转换为26进制
string lastCell = "A1:" + letterCol + row;
Range rng1;
rng1 = cpFileSh.get_Range(lastCell, Type.Missing);
Worksheet newsh = (Worksheet)tarFileWk.Sheets.Add(missing, missing, missing, missing);
Range rng2;
rng2 = newsh.get_Range(lastCell, Type.Missing);
rng1.Copy();
rng2.PasteSpecial(Microsoft.Office.Interop.Excel.XlPasteType.xlPasteAll, Microsoft.Office.Interop.Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, System.Type.Missing, System.Type.Missing);
rng2.EntireColumn.AutoFit();//自适应列宽,但是据说会降低运行效率╮(╯▽╰)╭如果不加这一行的话会按照源EXCEL的格式复制过来
((Range)newsh.Columns["A:B", System.Type.Missing]).ColumnWidth = 3;//将A,B两列的列宽修改为3(不是像素),如果只打算改A列的话把A:B改成A:A即可
((Range)newsh.Rows["1:2", System.Type.Missing]).RowHeight = 100;//将A.B两行的高度改为100
cpFileWk.Save();
cpFileWk.Close();
tarFileWk.Save();
tarFileWk.Close();
app.Quit();
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
//try { cpFileWk.Save(); } catch (Exception e) { Console.WriteLine(e); }
//try { cpFileWk.Close(); } catch (Exception e) { Console.WriteLine(e); }
//try { tarFileWk.Save(); } catch (Exception e) { Console.WriteLine(e); }
//try { tarFileWk.Close(); } catch (Exception e) { Console.WriteLine(e); }
try { app.Quit(); } catch (Exception e) { Console.WriteLine(e); }
}
}
/// <summary>
/// 将获取到的列数转换为二十六进制以便于匹配excel中的列名
/// </summary>
/// <param name="n">获取的列数</param>
/// <returns></returns>
public static string ToNumberSystem26(int n)
{
string s = string.Empty;
while (n > 0)
{
int m = n % 26;
if (m == 0) m = 26;
s = (char)(m + 64) + s;
n = (n - m) / 26;
}
return s;
}
/// <summary>
/// 获取需复制文件的名称
/// </summary>
/// <param name="copyFolderPosition">需复制文件的路径</param>
///需要注意的是这里需要传入绝对路径,如果传入的是相对路径需要先转换成绝对路径
/// <returns></returns>
public string[] getFileName(string copyFolderPosition)
{
// string[] files = Directory.GetFiles(copyFolderPosition, "*.*", SearchOption.AllDirectories);包含子目录
string[] files = Directory.GetFiles(copyFolderPosition, "*.xls*", SearchOption.TopDirectoryOnly);//不包含子目录
//foreach (string file in files)
//{
// Console.WriteLine(file);
//}
//Console.ReadLine();
return files;
}
}
}
目标文件路径以及文件名如果不存在,则需要新建一个目标文件,方式如下,需使用NPOI
HSSFWorkbook book = new HSSFWorkbook();
ISheet sheet = book.CreateSheet("Sheet1");
FileStream stream = File.OpenWrite(targetPosition); ;
book.Write(stream);
stream.Close();
更新:这种方法可以把图片一起复制过来
Application app = new Application();
Workbook workbook1 = app.Workbooks._Open(targetPosition, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Worksheet sheet1 = workbook1.Worksheets["Sheet1"] as Worksheet;
Workbook workbook2 = app.Workbooks._Open(copyfilePosition, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Worksheet sheet2 = workbook2.Worksheets["Sheet1"] as Worksheet;
sheet2.Copy(Type.Missing, sheet1);
workbook1.Save();
//workbook2.Save();
workbook1.Close(false, Type.Missing, Type.Missing);
workbook2.Close(false, Type.Missing, Type.Missing);