关于ASP.Net的导入导出(6)
Com.urp.command.FileFrameWork(6)
上期写的文章后面,林子朋友回复说要我看看他封装的ExcelManager,去看了一下,写的不错,功能上可以说比我的excelHelper强了好多,包括的字体,背景,模版等内容。要说明的是,我写的helper只提供了一个快速读取和写入的解决办法,并不是为了封装excel的操作而封装,只是因为内容的需要,为了使自己的东西用起来方便而已,并不能拿来作为一个单独的类库使用的,希望对我写的内容有兴趣朋友要注意这一点。就算最后形成了可重用的类库,其主要作用也是封装的导入导出,我期望告诉大家的是我的思考过程。
还有朋友提到要完整的代码和使用的例子,其实我一直认为看别人的代码是一件很累的事,不过看例子倒是一个不错的选择,那以后会增加一些实例。 所有涉及到具体类型的读写处理放到AbstractFileAPI子类来实现,也就是ADOExcel,ComExcel作用我们举一个ComExcel的例子看一下,代码如下: 现在就能看出ExcelHelper,ArrayCollection的作用了,ArrayCollection的作用就相当于table,用来保存数据的,ComExcel通过调用ExcelHelper这个代理来实现功能。 1. 实例化一个AbstractBuilder,来决定使用何种交换类型 2. 实例化一个ImportDirector ImportDirector director = new ImportDirector(fileUpload.InputStream, modelName, fileUpload.ContentType, builder); 3. 实例化IFileAPI, IdataAdapter _dataAdapter = director.Build(); ImportDirector的Build()方法如下: public IDataAdapter Build() { IFileAPI fileAPI = builder.InstanceFileAPI(inputStream, modelName, fileType); IDataAdapter dataAdapter = builder.InstanceDataAdapter(modelName); dataAdapter.FileAPI = fileAPI; return dataAdapter; } freewiller.cnblogs.com
这次先来说一下我的项目里是怎么使用这个helper类的。一般的helper类都是用静态方法来实现的,但是我写的这个并不是这样子做的,因为考虑到速度的问题,不想每次都要来打开关闭文件,这一点是不能作为一个单独的类库的又一个原因。访问excel提供com,ADO两种方法,而我把这两种方法封装在了一个类里面,那么形式上肯定是调用helper的类会有两个,所以就有了两个类ADOExcel,ComExcel。经过修改和原来的类图可能有不一样,FileType包就变成现在的样子了:

/**//// <summary>
/// ComExcell 的摘要说明。
/// </summary>
public class ComExcel : AbstractFileAPI
{
public const string _fileType = "xls";
public const string _contentType = "application/vnd.ms-excel";
private ExcelHelper _helper;
private ArrayCollection _arrayCollection;
//将整个sheet装入ArrayCollection
private ArrayCollection GetValues(int rowEnd, int columnEnd)
{
Array columns = _helper.GetByRangeArray2(0, 0, 0, columnEnd);
Array rows = _helper.GetByRangeArray2(1, 0, rowEnd, columnEnd);
return new ArrayCollection(rows, columns);
} 
//将ArrayCollection写回sheet
private void SetValues(int rowEnd, int columnEnd, Array values)
{
if(values != null)
{
_helper.SetByRangeArray2(0, 0, rowEnd, columnEnd, values);
}
} 
public ComExcel(string path, string fileName) : base(path)
{
_fileName = fileName;
}
public ComExcel(Stream inputStream, string path, string fileName) : base(path)
{
_inputStream = inputStream;
_fileName = fileName;
_helper = new ExcelHelper();
}
//获取单元格
public override object Get(int rowIndex, int columnIndex)
{
return _arrayCollection.Get(rowIndex, columnIndex);
}
//获取行
public override object[] GetRowValue(int rowIndex)
{
return _arrayCollection.GetRow(rowIndex);
}
//新增行
public override void AddRowValue(object[] values)
{
_arrayCollection.AddRow(values);
}
//修改列名
public override void AddColumn(string columnName)
{
ColumnTexts.Add(columnName);
}
//获得列名,默认为sheet中的第0行
public override IList ColumnTexts
{
get
{
if(_columnTexts == null || _columnTexts.Count == 0)
{
_columnTexts = _arrayCollection.Columns;
}
return _columnTexts;
}
}
//打开一个现有sheet
public override void OpenFile()
{
try
{
_helper.OpenWorkBook(Path);
if(!_helper.OpenWorkSheet(0))
throw new Exception("找不到可用的Sheet, 本次导入不成功");
_arrayCollection = GetValues(_helper.UsedRowCount - 1, _helper.UsedColumnCount - 1);
}
catch(Exception ex)
{
throw ex;
}
}
//新建一个sheet
public override void NewFile()
{
try
{
this.Delete();
_helper.NewWorkBook();
if(!_helper.OpenWorkSheet(0))
throw new Exception("找不到可用的Sheet, 本次导入不成功");
_arrayCollection = new ArrayCollection();
}
catch(Exception ex)
{
throw ex;
}
}

//关闭文件
public override void CloseFile()
{
_helper.CloseSheet();
}
//保存并关闭文件
public override void CloseSaveFile()
{
SetValues(_arrayCollection.Count, ColumnCount - 1, _arrayCollection.ToArray2);
_helper.CloseSaveSheet(this.Path);
}

//列数
public override int ColumnCount
{
get
{
return _arrayCollection.Columns.Count;
}
}
//数据行数,不包括首行列名
public override int RowCount
{
get
{
return _arrayCollection.Count;
}
}
public override string FileType
{
get
{
return _fileType;
}
}
public override string ContentType
{
get
{
return _contentType;
}
}
}
然后涉及到流操作的那么都是有AbstractFileAPI来完成的,代码如下:

/**//// <summary>
/// AbstractFileAPI 的摘要说明。
/// </summary>
public abstract class AbstractFileAPI : IFileAPI
{
private string _path;
private LocalFile _localFile = null;
protected string _fileName = null;
protected Stream _inputStream = null;
protected ArrayList _columnTexts = null;
protected AbstractFileAPI(string path)
{
_path = path;
_localFile = new LocalFile();
}

IFileAPI 成员#region IFileAPI 成员
public abstract object Get(int rowIndex, int columnIndex);
public abstract object[] GetRowValue(int rowIndex);
public abstract void AddRowValue(object[] values);
public abstract void AddColumn(string columnName); 
public abstract IList ColumnTexts
{ get; }

public abstract int RowCount
{ get; }
public abstract int ColumnCount
{ get; }
public abstract void OpenFile();
public abstract void NewFile();
public abstract void CloseFile();
public abstract void CloseSaveFile();

//写入文件的流
public void WriteStream()
{
try
{
if(_localFile != null)
_localFile.Write(_inputStream, _path);
}
catch(Exception ex)
{
throw ex;
}
finally
{
}
}
//读取文件的流
public Stream ReadStream()
{
try
{
if(_localFile != null)
return _localFile.Read(_path);
return null;
}
catch(Exception ex)
{
throw ex;
}
finally
{
}
}
//新建文件
public void New()
{
try
{
if(_localFile != null)
_localFile.New(_path);
}
catch(Exception ex)
{
return ;
}
finally
{
if(_localFile != null)
_localFile.Close();
}
}
//删除文件
public void Delete()
{
try
{
if(_localFile != null)
_localFile.Delete(_path);
}
catch(Exception ex)
{
throw ex;
}
}
public void Open()
{
if(_localFile != null)
_localFile.Open(_path);
}
//关闭
public void Close()
{
try
{
if(_localFile != null)
_localFile.Close();
}
catch(Exception ex)
{
throw ex;
}
finally
{
if(_inputStream != null)
_inputStream.Close();
_inputStream = null;
_localFile = null;
_columnTexts = null;
}
}
public string GetResponse()
{
StringBuilder builder = new StringBuilder(); 
//写入列信息
for(int i = 0; i < this.ColumnCount; i++)
{
builder.Append(this.ColumnTexts[i].ToString() + "\t");
}
builder.Append("\n");
//写入数据信息
for(int i = 0; i < this.RowCount; i++)
{
for(int j = 0; j < this.ColumnCount; j++)
builder.Append(this.Get(i, j) + "\t");
builder.Append("\n");
}
return builder.ToString();
}
public abstract string FileType
{
get;
}
public abstract string ContentType
{
get;
}
public string FileName
{
get
{
return _fileName;
}
}
public string Path
{
get
{
return _path;
}
}
#endregion
}
AbstractBuilder类里有两组方法,一组是导入的时候调用的,一组是导出的时候调用的
再来举个例子,看一个初始化一个导入,Excel文件,的过程,交换类用 Collection。
这样子就把IFileAPI,IdataAdapter的实例化都提到了Builder包里,各自FileAPI层, DataAdapter层就不用去关心如何创建了。
posted on 2006-09-13 14:08 whoisyorudady 阅读(1670) 评论(1) 编辑 收藏
