Java操作Excel表(一) 首次源码分析和初次读写操作
Java操作Excel表(一) 首次源码分析和初次读写操作
前言
前段时间一直想着用Python来操作Excel表,但是发现自己由于长期使用Java,C++这种语法类型的语言后,实在是难以适应Python的语法,最后决定还是来用Java操作。在网上看到有一些jar包可以实现,于是我就去Maven网站上找了一下。导下依赖吧。
由于我也是第一次接触这个jar包,所以今天想先看一下源码和它的功能再来研究怎么使用。如果理解错了还望指出,多多交流。^_^
不想看源码想捡现成的可以直接翻到最下面^_^
看源码最快也最直接的方式就是把注释和方法名称,变量名称翻译了。英语不好的同学最好建议下载一个有道词典
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
Workbook类
英文意思是(计算机上面的工作簿)。这个类表示工作簿。包含各种工厂方法并提供提供对工作表访问的各种访问器。
public abstract class Workbook
{
/**
* 软件的当前版本
*/
private static final String VERSION = "2.6.12";
/**
* 构造函数
*/
protected Workbook() { }
/**
* 获取此工作簿中的工作表。使用此方法为大型工作表可能导致性能问题。
* @return 返回单个表的数组
*/
public abstract Sheet[] getSheets();
/**
* 获取表单名称
* @return 包含工作表名称的字符串数组
*/
public abstract String[] getSheetNames();
/**
获取此工作簿中的指定工作表如随附的技术说明所述,每次通话
getSheet强制重新读取工作表(出于内存原因)。因此,不要对这个方法进行不必要的调用。此外,
在客户端代码中不保留对Sheets的不必要的引用,如这将阻止垃圾回收器释放内存
@param index reQuired表的零索引
@return索引指定的工作表
*/
public abstract Sheet getSheet(int index)
throws IndexOutOfBoundsException;
/**
从工作簿中获取具有指定名称的工作表。如随附的技术说明所述,每次通话
getSheet强制重新读取工作表(出于内存原因)。因此,不要对这个方法进行不必要的调用。此外,
在客户端代码中不保留对Sheets的不必要的引用,如这将阻止垃圾回收器释放内存
@param name表名
@return指定名称的工作表,如果没有找到则为空
*/
public abstract Sheet getSheet(String name);
/**
* 软件版本的访问器
* @return the version
*/
public static String getVersion()
{
return VERSION;
}
/**
* 返回此工作簿中的工作表数目
* @return 此工作簿中的工作表数目
*/
public abstract int getNumberOfSheets();
/**
从工作簿获取命名单元格。如果这个名字指的是范围的单元格,则返回左上角的单元格。如果
无法找到名称,返回null。
这是一个方便的函数,可以快速访问内容的单细胞。如果您需要进一步的信息(如
工作表或范围内相邻的单元格)使用功能更丰富的方法,findByName,它返回一个范围列表
@param name要搜索的单元格名称/范围
*/
public abstract Cell findCellByName(String name);
/**
返回指定位置的单元格。“Sheet1 ! A4”。这与使用CellReferenceHelper与它的
相关的性能开销,因此它应该要节约使用
@param loc要检索的单元格
@return指定位置的单元格
*/
public abstract Cell getCell(String loc);
/**
从该工作簿获取指定的范围。Range对象返回
包含从左上到右下的所有单元格
范围的*。
如果指定的范围包含相邻的范围,
Range[]将包含一个对象;对不相邻的范围时,必须返回长度大于1的数组。
*如果指定范围包含单个单元格,则左上角和
*右下角的单元格将是相同的单元格
* @param name要搜索的单元格名称/范围
* @返回单元格的范围,如果范围不存在则为NULL
*/
public abstract Range[] findByName(String name);
/**
* 获取命名范围
* @return 返回工作簿中命名单元格的列表
*/
public abstract String[] getRangeNames();
/**
* 确定工作表是否受保护
* @return TRUE 如果工作簿受到保护,则为FALSE
*/
public abstract boolean isProtected();
/**
*解析excel文件。
*如果工作簿是密码保护的,则抛出PasswordException
*如果API的消费者希望以特定的方式处理这个问题
* @exception BiffException
* @exception PasswordException
*/
protected abstract void parse() throws BiffException, PasswordException;
/**
*关闭该工作簿,释放任何分配的内存
*用于垃圾收集
*/
public abstract void close();
/**
*一个工厂方法,它接受一个excel文件并读取其中的内容。
* @exception IOException
* @exception BiffException
* @param文件excel 97电子表格解析
* @return工作簿实例
*/
public static Workbook getWorkbook(java.io.File file)
throws IOException, BiffException
{
return getWorkbook(file, new WorkbookSettings());
}
/**
*一个工厂方法,它接受一个excel文件并读取其中的内容。
* @exception IOException
* @exception BiffException
* @param文件excel 97电子表格解析
* @param ws工作簿的设置
* @return工作簿实例
*/
public static Workbook getWorkbook(java.io.File file, WorkbookSettings ws)
throws IOException, BiffException
{
FileInputStream fis = new FileInputStream(file);
//始终关闭输入流,不管是否
//文件可以被解析感谢Steve Hahn
File dataFile = null;
try
{
dataFile = new File(fis, ws);
}
catch (IOException e)
{
fis.close();
throw e;
}
catch (BiffException e)
{
fis.close();
throw e;
}
fis.close();
Workbook workbook = new WorkbookParser(dataFile, ws);
workbook.parse();
return workbook;
}
/**
*一个工厂方法,它接受一个excel文件并读取其中的内容。
* @param是一个开放的流,这是excel 97电子表格要解析
* @return工作簿实例
* @exception IOException
* @exception BiffException
*/
public static Workbook getWorkbook(InputStream is)
throws IOException, BiffException
{
return getWorkbook(is, new WorkbookSettings());
}
/**
*一个工厂方法,它接受一个excel文件并读取其中的内容。
* @param是一个开放的流,这是excel 97电子表格要解析
* @param ws工作簿的设置
* @return工作簿实例
* @exception IOException
* @exception BiffException
*/
public static Workbook getWorkbook(InputStream is, WorkbookSettings ws)
throws IOException, BiffException
{
File dataFile = new File(is, ws);
Workbook workbook = new WorkbookParser(dataFile, ws);
workbook.parse();
return workbook;
}
/**
*使用给定的文件名创建一个可写的工作簿
* @param文件的工作簿复制
* @返回一个可写的工作簿
* @exception IOException
*/
public static WritableWorkbook createWorkbook(java.io.File file)
throws IOException
{
return createWorkbook(file, new WorkbookSettings());
}
/**
*使用给定的文件名创建一个可写的工作簿
* @param file要复制的文件
* @param ws全局工作簿设置
* @返回一个可写的工作簿
* @exception IOException
*/
public static WritableWorkbook createWorkbook(java.io.File file,
WorkbookSettings ws)
throws IOException
{
FileOutputStream fos = new FileOutputStream(file);
WritableWorkbook w = new WritableWorkbookImpl(fos, true, ws);
return w;
}
/**
创建一个可写的工作簿与给定的文件名作为副本通过的工作簿。一旦创建,可写的内容工作簿可能被修改
@param file复制的输出文件
@param在工作簿中复制
@返回一个可写的工作簿
@exception IOException
*/
public static WritableWorkbook createWorkbook(java.io.File file,
Workbook in)
throws IOException
{
return createWorkbook(file, in, new WorkbookSettings());
}
/**
创建一个可写的工作簿与给定的文件名作为副本通过的工作簿。一旦创建,可写的内容工作簿可能被修改
@param file复制的输出文件
@param在工作簿中复制
@param ws此工作簿的配置
@返回一个可写的工作簿
*/
public static WritableWorkbook createWorkbook(java.io.File file,
Workbook in,
WorkbookSettings ws)
throws IOException
{
FileOutputStream fos = new FileOutputStream(file);
WritableWorkbook w = new WritableWorkbookImpl(fos, in, true, ws);
return w;
}
/**
创建一个可写的工作簿作为副本通过的工作簿。一旦创建,可写的内容工作簿可能被修改
@param OS要写入的流
@param在工作簿中复制
@返回一个可写的工作簿
@exception IOException
*/
public static WritableWorkbook createWorkbook(OutputStream os,
Workbook in)
throws IOException
{
return createWorkbook(os, in, ((WorkbookParser) in).getSettings());
}
/**
创建一个可写的工作簿作为副本通过的工作簿。一旦创建,可写的内容工作簿可能被修改
@param OS要写入的输出流
@param在工作簿中复制
@param ws此工作簿的配置
@返回一个可写的工作簿
@exception IOException
*/
public static WritableWorkbook createWorkbook(OutputStream os,
Workbook in,
WorkbookSettings ws)
throws IOException
{
WritableWorkbook w = new WritableWorkbookImpl(os, in, false, ws);
return w;
}
/**
创建可写的工作簿。当工作簿关闭时,它将直接流到输出流。在这个
方式,一个生成的excel电子表格可以传递一个servlet到浏览器通过HTTP
@param OS输出流
@返回可写的工作簿
@exception IOException
*/
public static WritableWorkbook createWorkbook(OutputStream os)
throws IOException
{
return createWorkbook(os, new WorkbookSettings());
}
/**
创建可写的工作簿。当工作簿关闭时,它将直接流到输出流。在这个
方式,一个生成的excel电子表格可以传递一个servlet到浏览器通过HTTP
@param OS输出流
@param ws此工作簿的配置
@返回可写的工作簿
@exception IOException
*/
public static WritableWorkbook createWorkbook(OutputStream os,
WorkbookSettings ws)
throws IOException
{
WritableWorkbook w = new WritableWorkbookImpl(os, false, ws);
return w;
}
}
WritableWorkbook类
这个类的英文是 Writable Workbook "可写的工作簿",可见这个类是用来实现写操作的
public abstract class WritableWorkbook{
/**
* 单元格格式的默认字体
*/
public static final WritableFont ARIAL_10_PT =
new WritableFont(WritableFont.ARIAL);
/**
* 用于超链接的字体
*/
public static final WritableFont HYPERLINK_FONT =
new WritableFont(WritableFont.ARIAL,
WritableFont.DEFAULT_POINT_SIZE,
WritableFont.NO_BOLD,
false,
UnderlineStyle.SINGLE,
Colour.BLUE);
/**
* 单元格的默认样式
*/
public static final WritableCellFormat NORMAL_STYLE =
new WritableCellFormat(ARIAL_10_PT, NumberFormats.DEFAULT);
/**
* 用于超链接的样式
*/
public static final WritableCellFormat HYPERLINK_STYLE =
new WritableCellFormat(HYPERLINK_FONT);
/**
* 用于隐藏单元格内容的单元格格式
*/
public static final WritableCellFormat HIDDEN_STYLE =
new WritableCellFormat(new DateFormat(";;;"));
/**
* 由实现类使用的构造函数
*/
protected WritableWorkbook()
{
}
/**
*获取此工作簿中的工作表。使用此方法为
*大的工作表会导致性能问题。
* @return单个表的数组
*/
public abstract WritableSheet[] getSheets();
/**
*获取表单名称
* @return一个包含工作表名称的字符串数组
*/
public abstract String[] getSheetNames();
/**
*获取此工作簿中的指定工作表
* @param index reQuired表的零索引
* @return索引指定的工作表
* @exception indexoutofboundexception当index指向一个不存在的对象时
*/
public abstract WritableSheet getSheet(int index)
throws IndexOutOfBoundsException;
/**
*从工作簿中获取具有指定名称的工作表
* @param name表名
* @return指定名称的工作表,如果没有找到则为空
*/
public abstract WritableSheet getSheet(String name);
/**
*返回指定位置的单元格。“Sheet1 ! A4”。这与使用CellReferenceHelper与它的
*相关的性能开销,因此它应该要节约使用
* @param loc要检索的单元格
* @return指定位置的单元格
*/
public abstract WritableCell getWritableCell(String loc);
/**
*返回工作簿中的工作表数量
* @返回工作簿中的工作表数量
*/
public abstract int getNumberOfSheets();
/**
*关闭此工作簿,并使分配的任何内存可用
*用于垃圾收集。也关闭底层的输出流,如果有必要。
* @exception IOException
* @exception WriteException
*/
public abstract void close() throws IOException, WriteException;
/**
*创建并返回指定位置的工作表
*与指定的名称
*如果指定的索引小于或等于0,则新工作表
在工作簿的开头创建。如果索引更大
*大于工作表的数量,则工作表在
*工作簿的结束。
* @param name表名
* @param index插入的索引号
* @return new sheet
*/
public abstract WritableSheet createSheet(String name, int index);
/**
*从不同的工作簿导入工作表。所有的都是深层拷贝吗
*元素
* @param name新工作表的名称
* @param索引新工作表在工作簿中的位置
* @param工作表(从另一个工作簿)合并到这个工作表
* @return new sheet
*/
public abstract WritableSheet importSheet(String name, int index, Sheet s);
/**
*在同一工作簿内的复制页。指定的工作表被复制到
*该位置的新工作表名称
* @param是要复制的页的索引
* @param name新工作表的名称
* @param索引新工作表的位置
*/
public abstract void copySheet(int s, String name, int index);
/**
*复制指定的工作表并将其放在索引处
*由参数指定
* @param是要复制的表格的名称
* @param name新工作表的名称
* @param索引新工作表的位置
*/
public abstract void copySheet(String s, String name, int index);
/**
*从工作簿中删除指定索引处的工作表
* @param index要删除的表索引
*/
public abstract void removeSheet(int index);
/**
*将工作簿中的指定工作表移动到另一个索引*位置。
* @param from mindex所需表的零基础索引
* @param toIndex要求的工作表的零基础索引
* @返回已移动的表
*/
public abstract WritableSheet moveSheet(int fromIndex, int toIndex);
/**
*以Excel格式写出工作簿中保存的数据
* @exception IOException
*/
public abstract void write() throws IOException;
/**
*指示该工作簿是否受保护
* @param prot受保护标志
*/
public abstract void setProtected(boolean prot);
/**
*设置工作簿的指定颜色的RGB值
* @param c要覆盖其RGB值的颜色
* @param r红色部分设置(0-255)
* @param g绿色部分设置(0-255)
* @param b蓝色部分设置(0-255)
*/
public abstract void setColourRGB(Colour c, int r, int g, int b);
/**
*该方法可用于创建其他可写克隆
*工作簿
* @param w workdock to copy
复制现在作为重载的一部分隐式发生
*工厂方法workbook . createworkbook
*/
public void copy(Workbook w)
{
//是一个抽象的方法——将方法主体留空吗
}
/**
*从工作簿获取命名单元格。这个名字指的是一个
*范围的单元格,则返回左上角的单元格。如果
*名称不能为,返回null
* @param name要搜索的单元格名称/范围
* @返回范围左上角的单元格,如果找到,NULL
*/
public abstract WritableCell findCellByName(String name);
/**
*从该工作簿获取指定的范围。Range对象返回
*包含从左上到右下的所有单元格范围的*。
*如果指定的范围包含相邻的范围,
* Range[]将包含一个对象;对不相邻的
*范围时,必须返回长度大于1的数组
*如果指定范围包含单个单元格,则左上角和
*右下角的单元格将是相同的单元格
* @param name要搜索的单元格名称/范围
返回单元格的范围
*/
public abstract Range[] findByName(String name);
/**
*获取命名范围
* @返回工作簿中命名单元格的列表
*/
public abstract String[] getRangeNames();
/**
*从工作簿中移除指定的命名范围。请注意,
删除名称可能导致使用该名称的公式
错误地计算结果
* @param name要删除的名称
*/
public abstract void removeRangeName(String name);
/**
*添加新命名区域到工作簿与给定的信息。
* @param name要创建的名称。
* @param sheet包含名称的表
* @param firstCol此名称所指的第一列。
* @param firstRow这个名称所指的第一行。
* @param lastCol此名称所指的最后一列。
* @param lastRow这个名称所指的最后一行。
*/
public abstract void addNameArea(String name,
WritableSheet sheet,
int firstCol,
int firstRow,
int lastCol,
int lastRow);
/**
设置一个新的输出文件。这允许使用相同的工作簿
*写入各种不同的输出文件而不必
*再次读入任何模板
* @param fileName文件名
* @exception IOException
*/
public abstract void setOutputFile(java.io.File fileName)
throws IOException;
}
Sheet
表示工作簿中的工作表。为个人提供句柄单元格或单元格行(按行或列分组)
public interface Sheet
{
/**
*返回在这行和这列指定的单元格。如果一个列/行组合是合并单元格组的一部分然后
(除非它是组的第一个单元格)一个空白单元格将被退回
* @param column列号
* @param row行号
* @return指定坐标的单元格
*/
public Cell getCell(int column, int row);
/**
*返回指定位置的单元格。“A4”。请注意,这
*方法与调用getCell(CellReferenceHelper.getColumn(loc)相同,
* CellReferenceHelper.getRow(loc))及其隐式性能
*字符串解析的开销。因此,这种方法应该
要节约使用
* @param loc单元格引用
* @return指定坐标的单元格
*/
public Cell getCell(String loc);
/**
*返回此工作表中的行数
* @返回本表的行数
*/
public int getRows();
/**
*返回此工作表的列数
* @返回本页的列数
*/
public int getColumns();
/**
*返回*中的列数获取指定行的所有单元格
* @param row要返回单元格的行
* @return表中给定行上的单元格
* @返回本页的列数
*/
public Cell[] getRow(int row);
/**
*获取指定列上的所有单元格
* @param col要返回的单元格的列
* @return指定列上的单元格
*/
public Cell[] getColumn(int col);
/**
*获取指定列上的所有单元格
* @param col the column获取工作表的名称
* @return要返回单元格的表名
* @return指定列上的单元格
*/
public String getName();
/**
*确定工作表是否被隐藏
* @返回是否隐藏表
* @ getSettings()方法已弃用
*/
public boolean isHidden();
/**
*确定工作表是否受保护
* @返回表是否受保护
* @ getSettings()方法已弃用
*/
public boolean isProtected();
/**
*获取其内容与传入字符串匹配的单元格。如果没有找到匹配,则返回null。搜索被执行
*以行为单位,所以行数越低,越多算法将有效执行
* @param内容要匹配的字符串
* @return其内容与参数匹配的Cell,如果没有找到则为空
*/
public Cell findCell(String contents);
/**
*获取其内容与传入字符串匹配的单元格。如果没有找到匹配,则返回null。搜索被执行
*以行为单位,所以行数越低,越多算法将有效执行
* @param内容要匹配的字符串
* @param firstCol范围内的第一列
* @param firstRow范围的第一行
* @param lastCol范围内的最后一列
* @param lastRow范围内的最后一行
* @param reverse表示是否执行反向搜索
* @return其内容与参数匹配的Cell,如果没有找到则为空
*/
public Cell findCell(String contents,
int firstCol,
int firstRow,
int lastCol,
int lastRow,
boolean reverse);
/**
*获取其内容与传入的正则表达式字符串匹配的单元格。如果没有找到匹配,则返回null。搜索被执行
*以行为单位,所以行数越低,越多算法将有效执行
* @param pattern匹配的正则表达式字符串
* @param firstCol范围内的第一列
* @param firstRow表示数组的第一行
* @param lastCol范围内的最后一列
* @param lastRow范围内的最后一行
* @param reverse表示是否执行反向搜索
* @return其内容与参数匹配的Cell,如果没有找到则为空
*/
public Cell findCell(Pattern pattern,
int firstCol,
int firstRow,
int lastCol,
int lastRow,
boolean reverse);
/**
*获取其内容与传入字符串匹配的单元格。如果没有找到匹配,则返回null。搜索被执行
*以行为单位,所以行数越低,越多算法将有效执行。该方法不同
在findCell方法中,只有带标签的单元格是查询-所有数字单元被忽略。这应该提高性能。
* @param contents the string to match
* @return 内容与参数匹配的Cell,如果没有找到则为空
*/
public LabelCell findLabelCell(String contents);
/**
*获取此工作表上的超链接
* @return一个超链接数组
*/
public Hyperlink[] getHyperlinks();
/**
*获取已在此工作表中合并的单元格
* @return range对象的数组
*/
public Range[] getMergedCells();
/**
*获取在特定工作表上使用的设置
* @返回工作表设置
*/
public SheetSettings getSettings();
/**
*获取指定列的列格式
* @param col列号
* @返回列的格式,如果列没有特定的格式,则返回NULL
* @deprecated使用getColumnView和CellView bean代替
*/
public CellFormat getColumnFormat(int col);
/**
*获取指定列的列宽度
* @param col列号
* @return列宽度,如果列没有宽度,则为默认宽度
* 指定的格式
* @deprecated使用getColumnView代替
*/
public int getColumnWidth(int col);
/**
*获取指定列的列宽度
* @param col列号
* @return列格式,如果没有覆盖,则返回默认格式
指定的
*/
public CellView getColumnView(int col);
/**
*获取指定列的行高
* @param row行号
* @return行高度,如果列没有高度,则返回默认高度
* 指定的格式
* @deprecated使用getRowView代替
*/
public int getRowHeight(int row);
/**
*获取指定列的行高
* @param row行号
* @return行格式,如果没有格式,可能是默认格式
* 指定
*/
public CellView getRowView(int row);
/**
*访问表上的图像数量
* @返回本页图片的数量
*/
public int getNumberOfImages();
/**
*图像访问器
* @param I基于0的图像编号
* @return指定位置的图像
*/
public Image getDrawing(int i);
/**
*此页上分页符的访问器
* @return本页的分页符
*/
public int[] getRowPageBreaks();
/**
*此页上分页符的访问器
* @return本页的分页符
*/
public int[] getColumnPageBreaks();
}
源码看完了,简单操作感受一下
实体类
为了方便最后发送Json给前端,所以这里就弄个实体类,把Excel当成数据库来用
class ExcelDo{
private String userName; //姓名
private String company; //公司
}//记得get set
读取操作
由于读取Excel表,由于读出来的都是根据列的顺序来,为了不写一大堆的if,故使用循环来搞定。为了防止循环导致的数组越界,封装了一个辅助方法。第一次写,如果有更好的方法还望多多指教
/**
* 读取操作
* @throws IOException
* @throws BiffException
*/
public List<ExcelDo> getExcelList() throws IOException, BiffException {
List<ExcelDo> excelDoList = new ArrayList<ExcelDo>(); //创建列表
File xlsFile = new File("E:/ExcelProject/test.xls"); //文件目录
Workbook workbook = Workbook.getWorkbook(xlsFile); //获得工作簿对象
Sheet sheet = workbook.getSheet(0); //获得工作表
int rows = sheet.getRows(); //获得行
int cols = sheet.getColumns(); //获得列
int index = 0;
for(int i = 0; i < rows; i++){ //读取数据
index = 0;
ExcelDo excelDo = new ExcelDo();
excelDo.setUserName(sheet.getCell(index,i).getContents());
index = getIndex(index,cols); //每次添加完都调用一次
excelDo.setCompany(sheet.getCell( index,i).getContents());
excelDoList.add(excelDo); //保存到列表中最后用来返回
}
workbook.close();
return excelDoList;
}
/**
* 循环时定义坐标,防止坐标越界 用于 辅助 getExcelList()
* @param index
* @param col
* @return
*/
private Integer getIndex(int index, int col){
index++;
if(index > col){
index = col;
}
return index;
}
测试
public static void main(String[] args) throws IOException, BiffException{
ExcelService excelService = new ExcelServiceImpl();
List<ExcelDo> excelList = excelService.getExcelList();
for(ExcelDo excelDo : excelList){
System.out.println(excelDo.toString());
}
}
写操作
/**
* 添加数据
* @param row 行数
* @param col 列数
* @param data 数据
* @throws IOException
* @throws WriteException
*/
public void writeExcel(int row, int col,String data) throws IOException, WriteException {
File xlsFile = new File("E:/ExcelProject/alvin.xls");
// 创建一个工作簿
WritableWorkbook workbook = Workbook.createWorkbook(xlsFile);
// 创建一个工作表
WritableSheet sheet = workbook.createSheet("Sheet1", 0);
sheet.addCell(new Label(col, row, data));
workbook.write();
workbook.close();
}
测试
public static void main(String[] args) throws IOException, BiffException, WriteException {
ExcelService excelService = new ExcelServiceImpl();
excelService.writeExcel(2,2,"alvin");
}
完整代码
package com.alvin.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.alvin.domain.ExcelDo;
import com.alvin.service.ExcelService;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.Sheet;
public class ExcelServiceImpl implements ExcelService{
/**
* 添加数据
* @param row 行数
* @param col 列数
* @param data 数据
* @throws IOException
* @throws WriteException
*/
public void writeExcel(int row, int col,String data) throws IOException, WriteException {
File xlsFile = new File("E:/ExcelProject/alvin.xls");
// 创建一个工作簿
WritableWorkbook workbook = Workbook.createWorkbook(xlsFile);
// 创建一个工作表
WritableSheet sheet = workbook.createSheet("Sheet1", 0);
sheet.addCell(new Label(col, row, data));
workbook.write();
workbook.close();
}
/**
* 读取操作
* @throws IOException
* @throws BiffException
*/
public List<ExcelDo> getExcelList() throws IOException, BiffException {
List<ExcelDo> excelDoList = new ArrayList<ExcelDo>(); //创建列表
File xlsFile = new File("E:/ExcelProject/test.xls"); //文件目录
Workbook workbook = Workbook.getWorkbook(xlsFile); //获得工作簿对象
Sheet sheet = workbook.getSheet(0); //获得工作表
int rows = sheet.getRows(); //获得行
int cols = sheet.getColumns(); //获得列
int index = 0;
for(int i = 0; i < rows; i++){ //读取数据
index = 0;
ExcelDo excelDo = new ExcelDo();
excelDo.setUserName(sheet.getCell(index,i).getContents());
index = getIndex(index,cols); //每次添加完都调用一次
excelDo.setCompany(sheet.getCell( index,i).getContents());
excelDoList.add(excelDo); //保存到列表中最后用来返回
}
workbook.close();
return excelDoList;
}
/**
* 循环时定义坐标,防止坐标越界 用于 辅助 getExcelList()
* @param index
* @param col
* @return
*/
private Integer getIndex(int index, int col){
index++;
if(index > col){
index = col;
}
return index;
}
}