项目目的:实现AB两个表格的数据合成,将B表和A表相同的数据合成,然后将B表格中有的数据A表格中没有的数据搬移到A表
功能介绍:实现动态的数据整合,数据搬移,极大的提高数据对比的准确度和效率
例如下列表格样式
表A:
编号 | 型号 | 数量 |
101 | A | 10 |
110 | B | 11 |
120 | C | 12 |
119 | D | 13 |
表B:
编号 | 型号 | 数量 |
119 | D | 30 |
110 | B | 13 |
120 | C | 12 |
130 | F | 15 |
表C:
编号 | 型号 | 数量 |
101 | A | 10 |
110 | B | 24 |
120 | C | 24 |
119 | D | 43 |
130 | F | 15 |
三个表格基本展示了本次实现的功能:表C为最终表格,其合成了AB表中的相同数据,并将B表的数据叠加到新的表格中,将AB全部数据全部合成。
本次实现功能拓展性强,可以方便的适应各种形式的表格合成,详细代码参见如下链接,本篇就大概讲述一下基本的实现方法和思路。
以下是一段基本excel操作代码主要着重讲述对excel的操作,包括单元格数据的获取,数据的叠加,数据的搬移以及一些解决思路
(1)获取单元格的内容
using Microsoft.Office.Interop.Excel;
using System;
//using Microsoft.Offic
using System.IO;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Data;
using System.Configuration;
using Microsoft.Office.Core;
using System.Web;
namespace csgui
{
class ExcelCopyer
{
public const String SHEET_NAME_MAIN = "BOM";//(主MAINBOM)主表格
public const String SHEET_NAME_DISTRIBUTION = "BOM";//(DESTBOM)目标表格
public const String FLAG_DEST_SHEET = "标记"; // 主表格,Sheet页数据标识
//public const String FLAG_DISTRIBUTION_SHEET = "DESTBOM"; // 次表格 Sheet页数据标示
public delegate void UpdateExcelProgress(int detal);
/*进行sheet的查找,找出指定名称的sheet表格*/
/*dst MAIN表格所在路径 out_path DEST表格所在路径 */
public static int copy(String[] from, String main_path, out String dest_path, UpdateExcelProgress uep, int progressSum)
{
Application app = new Application();
Workbooks wbs = app.Workbooks;
_Workbook Main = null;
String ex = "";
_Worksheet mainSheet = null; // 声明主BOM
_Worksheet datasheet = null; //声明DESTBOM
float sheet_average = 10f; // 假设每个Excel有10个sheet
float eachSheetAverageProgress = progressSum / (from.Length * sheet_average); // 平均每个Sheet页的进度
try
{
Main = wbs.Open(main_path); //MAIN表格所在路径
// 在目标sheet中匹配相应的Sheet页(两个sheet页查找,完成基本的数据分析)
foreach (_Worksheet sheet in Main.Worksheets)
{
if (SHEET_NAME_MAIN.Equals(sheet.Name))
{
mainSheet = sheet;
String mainname = mainSheet.Cells[1, 1].Text;
String mainname2 = mainSheet.Cells[2, 1].Text;
}
}
// Console.WriteLine("main sheet: " + mainSheet == null ? "null" : mainSheet.ToString());
//与上面的合并就可以实现两个sheet表的同步合并检测
/* + " , distribution sheet: " + distributionSheet == null ? "null" : distributionSheet.ToString());*/
//_Workbook dstWb = wbs.Add(dst);
_Workbook Dest = null;
//设置MAINBOM和DESTBOM的索引起点
int mainRowStart = 8;
foreach (String path in from)
{
try
{
Dest = wbs.Open(path);//DEST目标表格所在路径
foreach (_Worksheet sheet1 in Dest.Worksheets)
{
if (SHEET_NAME_DISTRIBUTION.Equals(sheet1.Name))
{
datasheet = sheet1;
//进行第二部的数据确定
String s2 = datasheet.Cells[1, 1].Text;
if (FLAG_DEST_SHEET.Equals(s2))
{
// 是MAINBOM
//mainRowStart = addMainSheeCell(mainSheet, mainRowStart, sheet);
addMainSheeCell(datasheet, mainRowStart, mainSheet);
}
else
{
return 1;
}
}
//uep(average);
}
Dest.Close();
}
//异常处理函数,当数据读到空的时候直接关闭当下的EXCEL表
catch (Exception e)
{
if (Dest == null)
{
Dest.Close();
}
ex += ex + "\r\n" + e.Message;
continue;
}
}
//wb.Worksheets.Copy(Missing.Value, dstWb.Worksheets[dstWb.Worksheets.Count]);
}
catch (Exception e)
{
if (Main == null)
{
Main.Close();
}
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
dest_path = ex + "\r\n" + e.Message;
return -1;
}
finally
{
dest_path = ex;
}
String name = main_path;
String suffix = ".xlsx";
int idx = main_path.LastIndexOf('.');
if (idx > 0)
{
name = main_path.Substring(0, idx);
suffix = main_path.Substring(idx, main_path.Length - idx);
}
String newName = "";
for (int i = 1; i <= int.MaxValue; ++i)
{
newName = name + i + suffix;
if (!File.Exists(newName))
{
break;
}
}
dest_path = newName;
app.AlertBeforeOverwriting = false;
app.DisplayAlerts = false;
if ("导入进度表".Equals(Main.Worksheets.get_Item(1).Name))
{
Main.Worksheets.get_Item(1).Delete();
}
Main.SaveAs(newName);
Main.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
return 0;
}
//对dasheet[n,13]数据循环处理
public static int addOtherSheetCell(int num, _Worksheet datasheet_2)
{
String result = "0";
for (int i = 8; i <=num; i++)
{
datasheet_2.Cells[i, 13] = result;
}
return 0;
}
//将和main相同的数据进行更改
public static void change_datasheet( int num1,_Worksheet datasheet_3)
{
String result1 = "1";
datasheet_3.Cells[num1, 13] = result1;
changeCell(datasheet_3.Cells[num1, 13]);
}
//将二者差异化数据加载到最终表格中
public static void addTomainbom(int datasheet_num2, int mainsheet_num2, int[] s2, _Worksheet mainsheet_2, _Worksheet datasheet_4, int M)
{
_Worksheet mainsheet = null;
_Worksheet datasheet = null;
mainsheet = mainsheet_2;
datasheet = datasheet_4;
List<int> strList = new List<int>();
//两个lists实现数据从一个list中剔除不需要的数据,然后转换为新的数组
List<int> pass = new List<int>(s2);
int[] sum3 = new int[datasheet_num2 - 8];
//将datasheet个行生成一个新的list
for (int num = 8; num <= datasheet_num2; num++)
{
strList.Add(num);
}
//逆序去除制定的相同项目
var expectedList = strList.Except(pass);
int[] M3 = new int[datasheet_num2 - 8];
M3 = expectedList.ToArray();
for (int num3 = 0; num3 <= M3.Length - 1; num3++)
{
int m = M3[num3];
for (int index = 1; index <= 10; index++)
{
mainsheet.Cells[mainsheet_num2+1, index] = datasheet.Cells[m, index].Text;
}
mainsheet_num2++;
}
}
//设置单元格属性
/*函数功能:数据合并
实现思想:数据索引->数据替换->数据记录->数据叠加
实现步骤:框架(可以索引,替换)->数据叠加(生成有效表格)->数据进行有效的排序(最终结果)
*/
private static int addMainSheeCell(_Worksheet dataSheet1, int disRowStart, _Worksheet mainSheet1)
{
String code = null;
String code1 = null;
String standard = null;
String numbers = null;
String standard1 = null;
String numbers1 = null;
int M = 0;
int mainRowStart = disRowStart;
//DESTBOM行列数据
int dest_rows = dataSheet1.UsedRange.Rows.Count ;
//MAINBOM行列数据
int main_rows = mainSheet1.UsedRange.Rows.Count;
int [] s1 = new int[dest_rows]; //定义字符数组,将相同的行数进行保存
int rowIdx = 8;
addOtherSheetCell(dest_rows,dataSheet1);
//外部循环,检查mainbom的数据
for (int Main = 1; Main <= main_rows - 7; Main++)
{
//进行Mainbom的内部循环,进行内部与外部的数据对比
for (int Dest = 1; Dest <= dest_rows - 7; Dest++)
{
//code = mainSheet1.Cells[mainRowStart, 1].Text; // 产品名字
standard = mainSheet1.Cells[mainRowStart, 2].Text; // 产品规格
numbers = mainSheet1.Cells[mainRowStart, 10].Text; // 产品数量
int numbersDouble = int.Parse(numbers);
//code1 = dataSheet1.Cells[disRowStart, 1].Text; // 产品名字
standard1 = dataSheet1.Cells[disRowStart, 2].Text; // 产品规格
numbers1 = dataSheet1.Cells[disRowStart, 10].Text; // 产品数量
int numbersDouble1 = int.Parse(numbers1);
// if (string.Equals(code, code1) == true || string.Equals(standard, standard1) == true)//进行产品编号和产品规格的对比
if (string.Equals(standard, standard1) == true)//进行产品编号和产品规格的对比
{
// code = code1;
standard = standard1;
mainSheet1.Cells[mainRowStart, 10] = numbersDouble + numbersDouble1;
changeCell(mainSheet1.Cells[mainRowStart, 10]);//缺少数据的索引和合并,首先应该实现的是相同数据的叠加,为后者留下接口函数
s1[M] = disRowStart;
M++;
change_datasheet(disRowStart, dataSheet1); //改变相同的数据行
numbersDouble1 = 0;
numbersDouble = 0;
code1 = null;
standard1 = null;
numbers1 = null;
}
numbersDouble1 = 0;
numbersDouble = 0;
if (disRowStart < dest_rows)
{
disRowStart++;
}
}
if (mainRowStart < main_rows)
{
rowIdx = rowIdx + 1;
mainRowStart++;
disRowStart = 8;
code = null;
standard = null;
numbers = null;
}
if (mainRowStart >= main_rows)
{
addTomainbom(dest_rows, main_rows, s1, mainSheet1, dataSheet1, M);
}
}
return disRowStart;
}
private static void changeCell(Range range)//设置单元格数据的格式
{
// 所有文本居中
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
}
public static void openExcel(String path)
{
Application excel = new Application();
excel.Visible = true;
Workbook wb = excel.Application.Workbooks.Add(path);
// wb.Close();
//excel.Quit();
// System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);
}
/*
static void Main(string[] args)
{
String s;
copy(new String[] { "from1", "from2" }, "dst path", out s);
}
*/
}
}