我已经实现了解析员工详细信息的功能,同样我将需要解析销售,客户等,因为我需要再创建2个功能。代码将在所有函数中重复,唯一的区别是
有没有办法将重复代码移动到一个类并配置它以便重用它?
public List<Employee> ParseEmployee(string filePath)
{
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
List<Employee> empLst= new List<Employee>();
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
int rowCount = xlRowRange.Count;
int colCount = xlcolRange.Count;
for (int i = 2; i <= rowCount; i++)
{
Range cell1 = xlRange.Cells[i, 1] as Range;
Range cell2 = xlRange.Cells[i, 2] as Range;
Range cell3 = xlRange.Cells[i, 3] as Range;
object val1 = cell1.Value2;
object val2 = cell2.Value2;
object val3 = cell3.Value2;
Employee emp = new Employee();
emp.FirstName = val1.ToString();
emp.LastName = val2.ToString();
emp.EmpID = val3.ToString();
empLst.Add(emp);
Marshal.ReleaseComObject(cell1);
Marshal.ReleaseComObject(cell2);
Marshal.ReleaseComObject(cell3);
}
}
catch (Exception exp)
{
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
workBook.Close(false, Type.Missing, Type.Missing);
_excelApp.Quit();
Marshal.ReleaseComObject(xlRowRange);
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlcolRange);
Marshal.ReleaseComObject(wSheet);
Marshal.ReleaseComObject(wSheets);
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(workBooks);
Marshal.ReleaseComObject(_excelApp);
}
return empLst;
}
答案 0 :(得分:1)
我认为visitor pattern可能非常合适。您可以修改上面的函数以包含名为visitor
的参数。然后修改for循环以将相关数据传递给访问者对象:
for (int i = 2; i <= rowCount; i++)
{
visitor.VisitRow(xlRange.Cells, i);
}
visitor.VisitRow()
函数将提取所需的数据,并在内部保留对提取的对象的引用。您将拥有不同的访客,一个是雇主,一个是销售,客户等。
最后,你会写这样的东西:
Visitor employerVisitor = new EmployerVisitor();
Visitor salesVisitor = new SalesVisitor();
Parse("workbook-employers.xls", employerVisitor);
Parse("workbook-sales.xls", salesVisitor);
List<Employee> employers = employerVisitor.GetData();
List<Sale> sales = salesVisitor.GetData();
答案 1 :(得分:0)
您可以通过以下方式从泛型类中公开它:
public class ObjectParser<T>
{
public List<T> ParseObject(string filePath, Func<Range, T> f)
{
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
List<T> lst= new List<T>();
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
int rowCount = xlRowRange.Count;
int colCount = xlcolRange.Count;
for (int i = 2; i <= rowCount; i++)
{
lst.Add(f(xlRange));
}
}
catch (Exception exp)
{
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
workBook.Close(false, Type.Missing, Type.Missing);
_excelApp.Quit();
Marshal.ReleaseComObject(xlRowRange);
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlcolRange);
Marshal.ReleaseComObject(wSheet);
Marshal.ReleaseComObject(wSheets);
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(workBooks);
Marshal.ReleaseComObject(_excelApp);
}
return lst;
}
}
要使用它:
ObjectParser<Employee> op = new ObjectParser<Employee>()
op.Parse(filepath, r => /* insert code to handle Employee here */)
我担心的是,一些Marshall.ReleaseComObject()
调用被推送到传入的lambda,这使得它有点重量级。您能否告诉我们更多关于Employee与其他类型之间使用哪些单元格的差异?
答案 2 :(得分:0)
我已将我的代码重新计算为类似
的代码 class ExcelParser : IDisposable
{
bool disposed = false;
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
public bool Load(string filePath)
{
bool bFlag = true;
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
}
catch (Exception exp)
{
throw;
}
return bFlag;
}
public int GetRowCount()
{
int rowCount = 0;
if(xlRowRange != null)
rowCount = xlRowRange.Count;
return rowCount;
}
public string GetValue(int rowIndex, int colIndex)
{
string value = "";
Range cell = null;
try
{
cell = xlRange.Cells[rowIndex, colIndex] as Range;
object val = cell.Value2;
value = val.ToString();
}
catch (Exception exp)
{
}
finally
{
Marshal.ReleaseComObject(cell);
}
return value;
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{ // don't dispose more than once
if (disposing)
{
// disposing==true means you're not in the finalizer, so
// you can reference other objects here
GC.Collect();
GC.WaitForPendingFinalizers();
if (workBook != null)
workBook.Close(false, Type.Missing, Type.Missing);
if (_excelApp != null)
_excelApp.Quit();
if (xlRowRange != null)
Marshal.ReleaseComObject(xlRowRange);
if (xlRange != null)
Marshal.ReleaseComObject(xlRange);
if (xlcolRange != null)
Marshal.ReleaseComObject(xlcolRange);
if (wSheet != null)
Marshal.ReleaseComObject(wSheet);
if (wSheets != null)
Marshal.ReleaseComObject(wSheets);
if (workBook != null)
Marshal.ReleaseComObject(workBook);
if (workBooks != null)
Marshal.ReleaseComObject(workBooks);
if (_excelApp != null)
Marshal.ReleaseComObject(_excelApp);
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ExcelParser()
{
Dispose(false);
}
}
,调用代码如下所示
public List<Employee> Handle(string filePath)
{
List<Employee> empLst = new List<Employee>();
ExcelParser exlParser = new ExcelParser();
try
{
if (exlParser.Load(filePath))
{
int rowCount = exlParser.GetRowCount();
for (int i = 2; i <= rowCount; i++)
{
Employee emp = new Employee();
emp.FirstName = exlParser.GetValue(i, 1);
emp.LastName = exlParser.GetValue(i, 2);
emp.EmpID = exlParser.GetValue(i, 3);
empLst.Add(emp);
}
}
}
catch (Exception exp)
{
}
finally
{
exlParser.Dispose();
}
return empLst;
}
所以现在我可以在我想使用的任何地方重用解析器。请评论这是否正确