上一篇说了利用JXL的jar包来读取Excel的代码。在Java中,还可以用另外一种jar包来读取Excel的内容,那就是Apache的POI。

  这里和之前一样,需要导入POI的jar包,建议导入这三个:poi-4.0.0.jar,poi-ooxml-4.0.0.jar,poi-ooxml-schemas-4.0.0.jar,

  下载地址:https://mvnrepository.com/search?q=POI

  我们先从最小的概念开始,读取一个Cell,即Excel中一个“格子”的内容。

private static String getValue(Cell cell) {
if (null == cell) {
return "";
} else if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
// 返回布尔类型的值
return String.valueOf(cell.getBooleanCellValue());
} else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
// 返回数值类型的值
return String.valueOf(cell.getNumericCellValue());
} else {
// 返回字符串类型的值
return String.valueOf(cell.getStringCellValue());
}
}

    这里会根据每个格子里的数据类型不同,来获取不同的值。(这里设置了三种,布尔型,数字型,字符串型)

然后,根据我们来把整个行的内容存入一个List中。

    private static List<Object> getRow(Row xssfRow) {
List<Object> cells = new ArrayList<Object>();
if (xssfRow != null) {
for (short cellNum = 0; cellNum < xssfRow.getLastCellNum(); cellNum++) {
Cell xssfCell = xssfRow.getCell(cellNum);
cells.add(getValue(xssfCell));
}
}
return cells;
}

  这里的是从行的第1列开始读,因此,我们在设计Excel表格的时候,需要注意一下。

  不过,在这里我想说的是,我们除了需要读取Excel的内容外,我们还希望“按需读取”。什么意思呢?就是说,我们之前是按照Excel的固有格式或者数据结构来读取内容的,比如我去指定开始/结束行,开始/结束列。

这样的话,我就必须要知道我要读取的范围是什么。但是,一般来说,我们使用Excel的习惯不是这样的。我们习惯于把某列或某行的数据提取或者过滤出来。举个简单的例子来说:假如一个Excel中有A,B,C三列,我们只想要A,C列的数据而忽略B列,这样的话如果用之前的方法,就会很不方便。另外,如果我们需要一次读取N个Excel文件中的A列和C列,也需要对代码进行重新审视。

  为了能够“按需读取”,我们首先需要设计一下这个“需”。在这里,我们引入一个概念,就是构造器(当然,这个也算是一种简单的javaBean),下面就逐步来分析,怎么实现这些功能。

  按照之前我们对页面元素的定义,我们在这里对Excel里面的内容也进行以下定义,即假如我使用Excel存储页面元素的内容,我应该是以什么样的格式去写。一般来说我想以以下的方式:

  

  在这里,pageName是页面名称,positionName就是我们给想点击的页面元素起的名字,type是寻找方式,sec是等待时间,path是寻找元素的具体路径的值。

  在这个Excel中,第一行的列名为我们定义的页面元素属性名称,从第二行的内容开始,我们需要填写每个页面元素实际的属性值。

  那么在这里我们先做一个记录页面元素属性值的构造器,或者叫Bean

package webui.bean;

public class positionBean {
//此处定义的是Excel里面列的名字,必须要一模一样,才能正常读取相应的数据!
String pageName;
String positionName;
String path;
int sec;
String type;
public String getPageName() {
return pageName;
}
public void setPageName(String pageName) {
this.pageName = pageName;
}
public String getPositionName() {
return positionName;
}
public void setPositionName(String positionName) {
this.positionName = positionName;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getSec() {
return sec;
}
public void setSec(int sec) {
this.sec = sec;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

  我们根据页面元素记录的属性,编写了这个构造器后,我们怎么让Excel按照这个构造器的内容来读取数据呢?我们这里需要用到Java中类反射的概念。先看下面一段代码:

private static Map<String, Method> getSetMethod(Class<?> clz,List<Object> heads) {
Map<String, Method> map = new HashMap<String, Method>();
Method[] methods = clz.getMethods();
for (Object head : heads) {
for (Method method : methods) {
if (method.getName().toLowerCase().equals("set" + head.toString().toLowerCase())
&& method.getParameterTypes().length == 1) {
map.put(head.toString(), method);
break;
}
}
}
return map;
}

  这段代码稍微有些抽象,我们需要根据两个参数(泛型Class<?>来指代我们刚才书写的构造器,List<Object> heads来对应写在Excel里面第一行的列名),我这里用实例来说明一下。

  Excel上有页面元素属性的几列数据(参考之前的Excel图片),构造器里是通过方法返回来取得的实际数据的。如果,我们把相应的列名和相应的方法对应起来,这样就可以把数据对应起来了。例如:pageName对应setPageName(String pageName)这个方法。

Method[] methods = clz.getMethods();  //这一句,实际上是获取这个类的所有公共方法。  

  if (method.getName().toLowerCase().equals("set" + head.toString().toLowerCase())&& method.getParameterTypes().length == 1)

  //这个判定实际上也是一个过滤,也就是寻找来自于这个类当中,由编写构造器时,生成的setter方法。(如果方法的名字与set + head的小写字母相同,且方法的参数类型长度为1,即只有1个参数)

  {map.put(head.toString(), method);}

  //将头名与方法对应放入HashMap中。------>可以理解为(pageName对应setPageName方法)

  这样一来,我们就用一个HashMap把这个关系给对应起来了。

  我们在取得这个对应关系之后,我们需要用Java的反射机制,来调用具体的方法来设置pageName的值。

  首先,由于Method的invoke方法,参数必须是一个底层的Object,所以,我们设计我们这个设置值的方法必须有这几个参数:

  Object obj------>其实这个可以是positionBean这个类一个实例,List<Object> data --------> 这个是读取的Excel的具体数据集合,List<Object> heads -------->这个List是读取列名的集合,Map<String,Method> methods ----->这个就是我们之前获取的列名与方法的对应关系集合。

  来看下面一段代码

private static void setValue(Object obj, List<Object> data,List<Object> heads, Map<String, Method> methods)throws IllegalArgumentException, IllegalAccessException,InvocationTargetException {
    //在获取了对应关系的HashMap之后,我们要对这个Map进行遍历。
for (Map.Entry<String, Method> entry : methods.entrySet()) {
Object value = "";
int dataIndex = heads.indexOf(entry.getKey());
      //按照当前列的序号小于数据List的长度(例如数据List的长度为5,当前为0~4的情况)
if (dataIndex < data.size()) {
           //使用一个Object来取得当前项的数据。
value = data.get(heads.indexOf(entry.getKey()));
}
         //取得HashMap里对应的方法
Method method = entry.getValue();
        //取得方法里的第一个参数的类型
Class<?> param = method.getParameterTypes()[0];
        //如果参数类型为String
if (String.class.equals(param)) {
         //方法反射,将具体的值赋给列名所代表的obj。
method.invoke(obj, value);
          //如果参数类型为整数
} else if (Integer.class.equals(param) || int.class.equals(param)) {
          //加入判断是否为空字符,因为很多时候Excel里空着就是0的意思
if(value.toString()==""){
value=0;
}
          //方法反射
method.invoke(obj, new BigDecimal(value.toString()).intValue());
} else if (Long.class.equals(param) || long.class.equals(param)) {
if(value.toString()==""){
value=0;
}
method.invoke(obj, new BigDecimal(value.toString()).longValue());
} else if (Short.class.equals(param) || short.class.equals(param)) {
if(value.toString()==""){
value=0;
}
method.invoke(obj, new BigDecimal(value.toString()).shortValue());
} else {
// Date
method.invoke(obj, value);
}
}
}

  关于反射,可能稍微比较难于理解。我再贴一段代码,大家可以是否容易理解。

public class MethodDemo {
public static void main(String[] args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method[] methods = SampleClass.class.getMethods();
SampleClass sampleObject = new SampleClass();
methods[1].invoke(sampleObject, "data");
System.out.println(methods[0].invoke(sampleObject));
}
} class SampleClass {
private String sampleField; public String getSampleField() {
return sampleField;
} public void setSampleField(String sampleField) {
this.sampleField = sampleField;
}
}

  以上运行的结果为:

data  

  写了这么多,好像离我们的所想要的功能越来越近了。我们把Excel的列名和构造类中的方法关联,然后读取数据来给他们赋值。下一章我们就具体来“按需读取”Excel吧。

基于Java+Selenium的WebUI自动化测试框架(十一)-----读取Excel文件(POI)(1)的更多相关文章

  1. 基于Java+Selenium的WebUI自动化测试框架(一)---页面元素定位器

    对于自动化测试,尤其是UI的自动化测试.是很多做黑盒功能测试的同学,入门自动化测试一个最为直观的或者说最容易理解的途径之一. 对于手工测试和自动化测试的优劣,网上有很多论述,在这里不作展开讨论.但是, ...

  2. 基于Java+Selenium的WebUI自动化测试框架(十四)-----使用TestNG的Sample

    到目前为止,我们所写的东西,都是集中在如何使用Selenium和Java来定位和读取元素.那么,到底如何具体开展测试,如何实现参数化,如何实现判定呢?下面,我们来看看Java应用程序的测试框架吧. 当 ...

  3. 基于Java+Selenium的WebUI自动化测试框架(八)-----读取元素(XML文件)

    我们继续回到自动化测试框架的主线上来,在前面的文章中,我们定义一个页面元素的主要参数有:路径,找寻方式,等待时间,名称,这个四个参数.另外,我们还需要考虑一个问题,就是网站的页面. 举个例子来说,如果 ...

  4. 基于Java+Selenium的WebUI自动化测试框架(六)---浏览器初始化

    本篇我们来讨论,如何写一个浏览器初始化的类.在写之前,先思考一下,我们需要一个什么样的初始化? 先来看看使用原生的Java + selenium是怎么做的.(以firefox为例) System.se ...

  5. 基于Java+Selenium的WebUI自动化测试框架(十)-----读取Excel文件(JXL)

    之前,我们使用了读取XML文件的方式来实现页面元素的读取,并做成了基础页面类.下面,我们来进行一些扩展,通过Excel来读取页面元素. Excel的使用,大多数人应该都不陌生.那么Java读取Exce ...

  6. 基于Java+Selenium的WebUI自动化测试框架(九)-----基础页面类(BasePage)

    上篇我们写了java读取xml文件的类,实现了可以从xml文件读取元素的方式.那么,接下来我们需要考虑一个问题.我们拿了这些元素之后怎么去操作呢? 先来看看我们手工测试的时候是怎么进行的. 双击浏览器 ...

  7. 基于Java+Selenium的WebUI自动化测试框架(十二)-----读取Excel文件(POI)(2)

    上一篇我们讲了怎么利用Java的反射机制,将Excel的读取到的数据,赋值给我们构造函数中定义的变量. 接下来就简单了,我们将实际实现这个读取的简单过程.来看下面一段代码. private stati ...

  8. 基于Java+Selenium的WebUI自动化测试框架(十三)-----基础页面类BasePage(Excel)

    前面,我们讲了如何使用POI进行Excel的“按需读取”.根据前面我们写的BasePageX,我们可以很轻松的写出来基于这个“按需读取”的BasePage. package webui.xUtils; ...

  9. 基于Java+Selenium的WebUI自动化测试框架(五)------页面操作实现类

    在编写完Log类和监听类之后,终于要回到正轨上来了.我们继续开始写UIExcutor的实现类. PS:如果你想让你的报告更加美观一些.推荐使用reportNG这个jar包. 在项目中导入reportn ...

随机推荐

  1. Spring Boot拦截器实现并和swagger集成后使用拦截器的配置问题

    1. 定义拦截器 LoginInterceptor LoginInterceptor.java是整个登录认证模块中的核心类之一,它实现了HandlerInterceptor类,由它来拦截并过滤到来的每 ...

  2. LeetCode 13. 罗马数字转整数(Roman to Integer)

    13. 罗马数字转整数 13. Roman to Integer 题目描述 罗马数字包含以下七种字符: I,V,X,L,C,D 和 M. 字符        数值  I           1  V  ...

  3. 01_Android入门

    Android系统文件目录结构 / 代表系统的根目录 /data/app/ 存放着第三方的apk文件 /system/app/ 其中是系统中的应用安装文件 /data/data/packagename ...

  4. AOP+Token防止表单重复提交

    表单重复提交: 由于用户误操作,多次点击表单提交按钮 由于网速等原因造成页面卡顿,用户重复刷新提交页面 避免表单重复提交的方式: 1.页面上的按钮做防重复点击操作 2.在数据库中可以做唯一约束 3.利 ...

  5. ByteBuffer常见方法

    ByteBuffer的三个属性 limit:所有对Buffer读写操作都会以limit变量的值作为上限. position:代表对缓冲区进行读写时,当前游标的位置. capacity:代表缓冲区的最大 ...

  6. LeetCode第151场周赛(Java)

    这是我第一次写周赛的题目,而且还是虚拟的.从这次起,以后就将所有错过的题目都写到博客来.当然既然是我错的,那代码肯定不是我自己的.我会注明来源.并且我会自己敲一遍.多总结总是没坏处的. 另外比较糟糕的 ...

  7. 【C#】上级实验四

    1.虚方法练习 设计一个控制台应用程序,定义一个Shape类,具体要求如下: ()类中定义2个私有字段长度(length).宽度(breadth). ()类中定义相应公有属性分别对应上述2个字段: ( ...

  8. Linux系统模拟发送HTTP的get和post请求

    一.get请求: 1.使用curl命令: curl “http://www.baidu.com” 如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地 curl -i “http://www ...

  9. 最新大型三甲医疗信息管理系统软件C#体检系统成熟PEIS源码BS架构NET网络版本

    查看体检系统演示 本源码是成熟在用大型医疗信息管理系统体检系统PEIS源码BS架构,开发语言是 asp.net c#,数据库是sqlserver2008r2,开发工具vs2010. 功能模块: 1.前 ...

  10. c#自制抽奖小程序

    #region 第一部分界面设计 ; Button button = new Button(); Image[] images = new Image[N]; PictureBox[] picture ...