我正在尝试构建一个安装程序项目(Windows窗体),通过该项目我可以从目录中选择多个excel文件,从每个文件中复制内容,并将其附加到新的单个输出文件中。我正在VS 2017 Community Edition中使用Microsoft.Office.Interop.Excel
软件包。我仍在努力,但向正确的方向稍加推动会很有帮助。
说,我的目录中有100多个excel文件,每个excel工作簿至少包含1张纸。每张纸的结构相同。使用OpenFileDialog
:
listbox
中显示所选的文件名及其路径。 我不知道我到底要去哪里,我什至无法创建输出excel文件。到目前为止,这是我的工作:
Excel.Application excel;
Stream myStrm;
OpenFileDialog ofd = new OpenFileDialog();
private void button1_Click(object sender, EventArgs e)
{
ofd.InitialDirectory = "c:\\";
ofd.Title = "Please select the files to merge";
ofd.Filter = "Excel Files|*.xls;*.xlsx;*.xlsm";
//ofd.FileName = "ExportedData";
//ofd.DefaultExt = ".xlsx";
ofd.RestoreDirectory = true;
ofd.Multiselect = true;
//To store file path info
List<System.IO.FileInfo> fList = new List<System.IO.FileInfo>();
if (ofd.ShowDialog() == DialogResult.OK)
{
var fileName = ofd.FileName;
var tempFolderPath = Path.GetTempPath();
var templateFileLocation = Path.Combine(Directory.GetCurrentDirectory(), "Model", "ExcelTemplate.xlsx");
templateFileLocation = templateFileLocation.Replace("\\bin\\Debug\\", "\\");
foreach (String file in ofd.FileNames)
{
try
{
if((myStrm = ofd.OpenFile()) != null)
{
using (myStrm)
{
//to display file name in the 1st listbox
fileListBox.Items.Add(file.Substring(file.LastIndexOf('\\') + 1));
//to display the path of the file
pathListBox.Items.Add(file);
}
}
//to display the selected file count
fileCntLbl.Text = "You have selected " + ofd.FileNames.Length + " files";
ApplicationClass app = new ApplicationClass();
Workbook curWorkBook = null;
Workbook destWorkbook = null;
Worksheet workSheet = null;
Worksheet newWorksheet = null;
Object defaultArg = Type.Missing;
//FileInfo fi = null;
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
try
{
// Copy the source sheet
curWorkBook = app.Workbooks.Open(file, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg);
workSheet = (Worksheet)curWorkBook.Sheets[1];
workSheet.UsedRange.Copy(defaultArg);
// Paste on destination sheet
destWorkbook = app.Workbooks.Open(@"c:\\Results.xlxs", defaultArg, false, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg, defaultArg);
newWorksheet = (Worksheet)destWorkbook.Worksheets.Add(defaultArg, defaultArg, defaultArg, defaultArg);
newWorksheet.UsedRange._PasteSpecial(XlPasteType.xlPasteValues, XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
}
}
catch (Exception exc)
{
System.Windows.Forms.MessageBox.Show(exc.Message);
}
finally
{
if (curWorkBook != null)
{
curWorkBook.Save();
curWorkBook.Close(defaultArg, defaultArg, defaultArg);
}
if (destWorkbook != null)
{
destWorkbook.Save();
destWorkbook.Close(defaultArg, defaultArg, defaultArg);
}
}
app.Quit();
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
}
private void button2_Click(object sender, EventArgs e)
{
System.Windows.Forms.Application.Exit();
}
此solution有效,但不复制内容并产生错误。错误是这样的:
任何帮助/建议表示赞赏。感谢您的帮助。
我已经在stackexchange,codeproject和许多其他站点上尝试了所有解决方案。因此,请勿将其标记为重复项或家庭作业。
答案 0 :(得分:1)
请尝试使用Sheet.Copy函数,而不是复制/粘贴UsedRange。它将大大简化您的代码并减少潜在的错误点。 C# - How to copy a single Excel worksheet from one workbook to another?
答案 1 :(得分:1)
我知道我来不及回答这个问题,但这仍然可以帮助某人。
您可以在此处具有两个功能,一个用于打开文件,另一个用于复制内容。
在第一个函数中,您可以通过for循环打开任意数量的文件,如下所示:
void OpenFiles()
{
foreach (string strFile in sourceFiles) //sourceFiles is a list containing the file paths
{
bool b = false;
Excel.Workbook bookSource = app.Workbooks._Open(strFile, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
Excel.Worksheet sheetSource = bookSource.Worksheets[1] as Excel.Worksheet;
CopyData();
}
//finally save the file as your requirements and close all the open workbooks
}
void CopyData()
{
Excel.Worksheet lastsheet = null; //last sheet in the workbook
int limit = 1000000; //variable to check if your sheet has exceeded
try
{
var sheets = bookDest.Sheets;
lastsheet = (Excel.Worksheet)bookDest.Sheets[sheets.Count];
hc.ReleaseObject(sheets);
drc = lastsheet.UsedRange.Rows.Count; //no of rows used in result workbook
src = sheetSource.UsedRange.Rows.Count; //no of rows used in source workbook
//if else loop to check if you have exceeded 1st sheet limit before start copying
if ((drc + src) <= limit)
{
int sheetRowCount = sheetSource.UsedRange.Rows.Count;
Excel.Range range = sheetSource.get_Range(string.Format("A{0}", _headerRowCount), _columnEnd + sheetRowCount.ToString());
range.Copy(lastsheet.get_Range(string.Format("A{0}", _currentRowCount), Missing.Value));
_currentRowCount += range.Rows.Count;
}
else if ((drc >= limit && src >= limit) || drc >= limit || src >= limit || (drc + src) >= limit)
{
Excel.Worksheet newSheet = (Excel.Worksheet)bookDest.Worksheets.Add(After: lastsheet);
newSheet.Name = "Result " + (cnt++);
hc.ReleaseObject(lastsheet);
lastsheet = newSheet;
lastsheet.Activate();
CopyHeader(lastsheet);
//((Excel.Worksheet) this.app.ActiveWorkbook.Sheets[lastsheet]).Select();
int sheetRowCount = sheetSource.UsedRange.Rows.Count;
Excel.Range range = sheetSource.get_Range(string.Format("A{0}", _headerRowCount), _columnEnd + sheetRowCount.ToString());
range.Copy(lastsheet.get_Range(string.Format("A{0}", _currentRowCount), Missing.Value));
_currentRowCount += range.Rows.Count;
}
}
else
{
int sheetRowCount = sheetSource.UsedRange.Rows.Count;
Excel.Range range = sheetSource.get_Range(string.Format("A{0}", _headerRowCount), _columnEnd + sheetRowCount.ToString());
range.Copy(lastsheet.get_Range(string.Format("A{0}", _currentRowCount), Missing.Value));
_currentRowCount += range.Rows.Count;
}
}
catch (IndexOutOfRangeException)
{
MessageBox.Show("Some problem with the source file", "Copy error");
}
finally
{
ReleaseObject(lastsheet);
}
}
我已将上限限制为一百万。如果您认为此限制可能会超出您的才能,那么您可以减少它。
邀请您进行任何代码更改。
谢谢。
答案 2 :(得分:0)
或者,使用System.IO,可以使用以下命令将excel文件复制到新文件中:
File.WriteAllBytes(newFilePath, File.ReadAllBytes(initialFilePath));