900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 将excel表格数据转换为xml文本数据

将excel表格数据转换为xml文本数据

时间:2023-02-27 10:15:42

相关推荐

将excel表格数据转换为xml文本数据

原文:/archives/12

这篇blog主要是讲述java中poi读取excel,并将excel中的数据转化为xml文本中的数据,而excel的版本包括:之前和之后两个版本, 即excel的后缀名为:xls和xlsx。

该项目的目录结构如下图:

项目中所需要的jar包如图中lib目录所示。 所用的Excel数据如下图所示:(不同excel版本中的数据相同)

大家也可以用自己的数据,但是,数据请符合以下规则,(如不符合以下规则,请自行修改代码后再使用): 1、我们要读取的sheet要放在excel中的最前面 2、sheet中的第一行为字段行 3、sheet中必须要有一个字段为Key的列 4、sheet中的第二行为该字段的解释 5、sheet中的第三行为该字段的类型 6、sheet中的第四行为标志位,该标志位的含义为:当Key字段的这个值为C的时候,只生成client端使用的xml文件(其他字段的该值为C或者A就放进该xml文件中,为S就不会放入),当Key字段的这个值为S的时候,只生成server端使用的xml文件(其他字段的该值为S或者A就放进该xml文件中,为C就不会放入),当值为A的时候,即生成client端使用的xml文件,也生成server端使用的xml文件(其他字段的该值为C时,放入生成的client端使用的xml文件中,其他字段的值为S时,放入生成的server端使用的xml文件中,其他字段的值为A时,即放入生成的client端使用的xml文件中,又放入server端使用的xml文件中)。 运行结果如下所示: client端运行结果:

server端运行结果:

代码部分:

ConfigUtil.java主要负责获取我们配置在config.properties里面的数据

package util;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.Properties;public class ConfigUtil {//获取一个文本输入流,该文本输入流所输入的是config.properties配置文件public FileInputStream getFileInputStream(){//声明一个文本输入流FileInputStream in = null;try {//实例化文本输入流,输入config.properties配置文件in = new FileInputStream("conf/config.properties");} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}//返回该文本输入流return in;}//关闭一个文本输入流public void closeFileInputStream(FileInputStream in){try {//关闭文本输入流in.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//通过Properties获取名称为pathName的值public String getPath(Properties pro, String pathName) {//获取本项目的根目录String firstPath = ConfigUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();//获取本项目根目录的上一级目录firstPath = firstPath.substring(0, firstPath.lastIndexOf("/"));//获取config.properties中配置的名称为pathName的属性值String lastPath = pro.getProperty(pathName);//判断lastPath是否是以..开头的if (lastPath.substring(0, 2).equals("..")) {//如果lastPath是以..开头的,我们就调用该方法获取它的绝对路径lastPath = getPath(firstPath, lastPath);} else {//如果不是以..开头的,我们再去判断是否是以.开头的if (lastPath.substring(0, 1).equals(".")) {//如果是以.开头的,我们在这里处理,获取他的绝对路径lastPath = firstPath + lastPath.substring(1, lastPath.length());}}//返回该绝对路径return lastPath;}//当配置中的路径是以..开头的时候,我们通过该方法可以获取到我们要的文件夹的绝对路径public String getPath(String firstPath, String lastPath) {//判断lastPath中是否存在..if (lastPath.indexOf("..") != -1) {//将firstPath进行截取,去掉firstPath的最后一个目录结构firstPath = firstPath.substring(0, firstPath.lastIndexOf("/"));//将lastPath进行截取,去掉lastPath的前3个字符,(../)lastPath = lastPath.substring(3, lastPath.length());//递归调用return getPath(firstPath, lastPath);} else {//当lastPath中不存在..的时候,我们将firstPath和lastPath进行拼接,获得绝对路径return firstPath + "/" + lastPath;}}}

ExcelToXml.java中的代码为逻辑代码,负责读取excel中的数据,解析,并生成xml文件

package impl;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.util.ArrayList;import java.util.List;import java.util.Properties;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.poifs.filesystem.POIFSFileSystem;import org.apache.poi.ss.usermodel.Cell;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import util.ConfigUtil;public class ExcelToXml {public static void main(String[] args) throws Exception {ExcelToXml excelToXml = new ExcelToXml();excelToXml.excelToXml();}@SuppressWarnings("unchecked")public void excelToXml() {// 实例化ConfigUtil类,用来获取config.properties中配置的属性ConfigUtil configUtil = new ConfigUtil();// 打开一个文件输入流,这个输入流读取了config.propertiesFileInputStream in = configUtil.getFileInputStream();// 实例化一个properties配置文件的工具类Properties pro = new Properties();try {// 载入文件输入流中的数据pro.load(in);} catch (IOException e2) {// TODO Auto-generated catch blocke2.printStackTrace();}// 获得ExcelPath的路径,该路径在config.properties中可以配置成相对路径,也可以配置成绝对路径,// 但是,如果是相对路径,这个路径是相对于本项目根目录的,不是相对于本类文件的String excelPath = configUtil.getPath(pro, "ExcelPath");// 获得ClientPath的路径,该路径在config.properties中可以配置成相对路径,也可以配置成绝对路径,// 但是,如果是相对路径,这个路径是相对于本项目根目录的,不是相对于本类文件的String clientPath = configUtil.getPath(pro, "ClientPath");// 获得ClientPath的路径,该路径在config.properties中可以配置成相对路径,也可以配置成绝对路径,// 但是,如果是相对路径,这个路径是相对于本项目根目录的,不是相对于本类文件的String serverPath = configUtil.getPath(pro, "ServerPath");// 获得需要在生成的xml文件中声明的版本号,字符集的配置String xmlDeclaration = pro.getProperty("xmlDeclaration");System.out.println("ExcelPath = " + excelPath);System.out.println("ClientPath = " + clientPath);System.out.println("ServerPath = " + serverPath);System.out.println("XmlDeclaration = " + xmlDeclaration);// 文件输入流使用完毕,关闭这个文件输入流configUtil.closeFileInputStream(in);// 读取Excel的存放路径,这个路径需要指向一个已存在的文件夹,不然会报错,因为要根据这里面的excel来生成xml,所以,如果文件夹不存在,我不会主动去创建File file = new File(excelPath);// 判断该file是不是一个文件夹if (file.isDirectory()) {// 获取文件夹中的所有文件File[] excelFiles = file.listFiles();// 遍历这些文件for (File excelFile : excelFiles) {// 判断是否是文件if (excelFile.isFile()) {// 获取文件名(包括后缀名)String excelName = excelFile.getName();// 获取文件名(去掉后缀名)String firstName = excelName.substring(0, excelName.lastIndexOf("."));// 获取文件的后缀名String excelLastName = excelName.substring(excelName.lastIndexOf(".") + 1, excelName.length());// 声明一个workbook,用来操作我们要操作的excel文档用的Workbook wb = null;// 声明一个文本输入流,用来读取我们要操作的excel文档用的FileInputStream fis = null;try {// 实例化文本输入流fis = new FileInputStream(excelFile);} catch (FileNotFoundException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}// 声明一个sheet,用来操作我们要操作的sheetSheet sheet = null;// 声明一个row,这个row用来操作sheet中的第一列,这里的规则第一列存放的是字段名Row namesRow = null;// 声明一个row,这个row用来操作sheet中的第二列,这里的规则第二列存放的是字段说明Row annotationRow = null;// 声明一个row,这个row用来操作sheet中的第三列,这里的规则第三列存放的是字段的类型Row classRow = null;// 声明一个row,这个row用来操作sheet中的第四列,这里的规则第四列存放的是一个标志位,// 标志这个字段生成的时候是放入client使用的xml文件中的,还是放入server使用的xml文件中的,// C表示放入client使用的xml文件中,S表示放入server使用的xml文件中,A表示在client和server使用的xml文件中都放入Row typeRow = null;// 我们每一张excel表中必须要有一个叫Key的字段,这个字段是确定数据的唯一性的,相当于id,这里声明的keyNum是表示Key这个字段在sheet中的第几列int keyNum = 0;// 声明一个boolean值,该值表示是否要生成client端使用的xml文件,当key的标志位为C的时候只生成client端使用的xml文件,当key的标志位为S的时候,// 只生成server端使用的xml文件,当key的标志位为A的时候,表示既要生成client端使用的xml文件,又要生成server端使用的xml文件boolean cfal = false;// 声明一个boolean值,该值表示是否要生成server端使用的xml文件boolean sfal = false;// 声明一个List,用来存放所有的字段名List<String> nameList = null;// 声明一个List,用来存放所有的字段说明List<String> annotationList = null;// 声明一个List,用来存放所有的字段类型List<String> classList = null;// 声明一个List,用来存放所有的要放入client端使用的xml文件的字段的位置List<Integer> cnums = null;// 声明一个List,用来存放所有的要放入server端使用的xml文件的字段的位置List<Integer> snums = null;// 实例化一个xml的名称,所生成的xml文件就叫这个名字String xmlName = firstName + ".xml";// 声明一个xml文件,这个文件就是我们要生成的xml文件File xmlFile = null;// 声明一个字符串,这个字符传存放的是我们要放入xml文件中的内容String outputStr = "";// 判断该文件的后缀名是否是xls结尾的,主要是为了区分excel的版本if (excelLastName.equals("xls")) {POIFSFileSystem fs = null;try {fs = new POIFSFileSystem(fis);// 实例化workbookwb = new HSSFWorkbook(fs);} catch (IOException e) {e.printStackTrace();}// 判断该文件的后缀名是否是xlsx结尾的,主要是为了区分excel的版本} else if (excelLastName.equals("xlsx")) {try {// 实例化workbookwb = new XSSFWorkbook(fis);} catch (IOException e) {e.printStackTrace();}// 不是excle文件就跳过本次循环} else {continue;}// 实例化sheet,这里我默认取的是文件中的第一个sheet,大家也可以改成用sheet名来取的,wb.getSheet("sheet名");sheet = wb.getSheetAt(0);// 获取sheet中的第一行,也就是字段名那一行namesRow = sheet.getRow(0);// 获取第一行的内容Object[] obj = getNames(namesRow);// 将第一行的内容赋值给nameListnameList = (List<String>) (obj[0]);// 获得key在excel表中的哪一列keyNum = (int) (obj[1]);// 判断,如果第一行为空,就跳过本次循环if (nameList == null || nameList.size() == 0) {continue;}// 获得sheet中的第二行,也就是字段说明那一行annotationRow = sheet.getRow(1);// 获得字段说明的内容annotationList = getAnnotations(annotationRow);// 判断,如果第二行为空,就跳过本次循环if (annotationList == null || annotationList.size() == 0) {continue;}// 获得sheet中的第三行,也就是字段类型那一行classRow = sheet.getRow(2);// 获得字段类型的内容classList = getClasses(classRow);// 判断,如果第三行为空,就跳过本次循环if (classList == null || classList.size() == 0) {continue;}// 获得sheet中的第四行,也就是标志位那一行typeRow = sheet.getRow(3);// 获得标志位的信息Object[] tobj = getTypes(typeRow, keyNum);// 获得哪些列是要放入到client端使用的xml文件中的cnums = (List<Integer>) tobj[0];// 获得哪些列是要放入到server端使用的xml文件中的snums = (List<Integer>) tobj[1];// 获取是否生成客户端xml文件cfal = (boolean) tobj[2];// 获取是否生成server端使用的xml文件sfal = (boolean) tobj[3];// 判断是否生成client端使用的xml文件if (cfal) {// 获取要向xml文件中打印的内容outputStr = getOutputStr(nameList, annotationList, classList, firstName, sheet, cnums,xmlDeclaration, false);System.out.println(outputStr);// 实例化client端使用的xml文件xmlFile = new File(clientPath + "/" + xmlName);try {// 将内容写入到client端使用的xml文件中writer(xmlFile, outputStr);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// 判断是否生成server端使用的xml文件if (sfal) {// 获取要向xml文件中打印的内容outputStr = getOutputStr(nameList, annotationList, classList, firstName, sheet, snums,xmlDeclaration, true);System.out.println(outputStr);// 实例化server端使用的xml文件xmlFile = new File(serverPath + "/" + xmlName);try {// 将内容写入到server端使用的xml文件中writer(xmlFile, outputStr);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}}// 获取excel中第一行所包含的信息private Object[] getNames(Row namesRow) {// 实例化一个List,该list中存放的是所有的字段名List<String> nameList = new ArrayList<String>();// 实例化一个int值,该值表示key字段在excel中的位置int keyNum = 0;// 实例化一个object类型的数组,该数组中存放的是所有的字段名和key字段的位置Object[] obj = new Object[2];// 判断namesRow这个行是否为空if (namesRow != null) {// 遍历namesRow这一行for (int i = 0; i < namesRow.getLastCellNum(); i++) {// 获取单元格Cell cell = namesRow.getCell(i);// 判断单元格是否为空if (cell != null) {// 添加单元格的内容到nameList中nameList.add(cell.getStringCellValue());// 判断这个单元格的内容是不是Keyif (cell.getStringCellValue().equalsIgnoreCase("Key")) {// 记录Key的位置keyNum = i;}}}}// 将所有的字段名放入obj[0]obj[0] = nameList;// 将key列的位置放入obj[1]obj[1] = keyNum;// 返回objreturn obj;}// 获取字段说明那一行的数据private List<String> getAnnotations(Row annotationRow) {// 声明一个list,用来存放所有的字段说明List<String> annotationList = new ArrayList<String>();// 判断,字段说明那一行是否为空if (annotationRow != null) {// 遍历字段说明这一行所有的单元格for (int i = 0; i < annotationRow.getLastCellNum(); i++) {// 获取单元格Cell cell = annotationRow.getCell(i);// 判断单元格是否为空if (cell != null) {// 将单元格中的内容放入List中annotationList.add(cell.getStringCellValue());}}}// 返回所有的字段说明return annotationList;}// 获取字段类型那一行的数据private List<String> getClasses(Row classRow) {// 声明一个list,用来存放所有的字段类型List<String> classList = new ArrayList<String>();// 判断这一行是否为空if (classRow != null) {// 遍历这一行的所有单元格for (int i = 0; i < classRow.getLastCellNum(); i++) {// 获取单元格Cell cell = classRow.getCell(i);// 判断单元格是否为空if (cell != null) {// 将单元格的内容存放到list中classList.add(cell.getStringCellValue());}}}// 返回所有的字段类型return classList;}// 获取标志位那一行的信息private Object[] getTypes(Row typeRow, int keyNum) {// 声明一个List,用来存放所有要放入生成的client端的xml文件中的数据位置信息List<Integer> cnums = new ArrayList<Integer>();// 声明一个List,用来存放所有要放入生成的server端的xml文件中的数据位置信息List<Integer> snums = new ArrayList<Integer>();// 声明一个boolean值,用来判断是否要生成client端的xml文件boolean cfal = false;// 声明一个boolean值,用来判断是否要生成server端的xml文件boolean sfal = false;// 声明一个object数字,用来存放这一行所要返回的信息Object[] obj = new Object[4];// 判断这一行是否为空if (typeRow != null) {// 遍历这一行的所有单元格for (int i = 0; i < typeRow.getLastCellNum(); i++) {// 获取单元格Cell cell = typeRow.getCell(i);// 判断单元格是否为空if (cell != null) {// 判断单元格的内容是否为C,为C表示这一列要放入到生成的client端要使用的xml文件中if (cell.getStringCellValue().equals("C")) {// 添加单元格位置到cnums中cnums.add(i);// 判断是否是key列,如果是,表示要生成client端使用的xml文件if (keyNum == i) {// 将判断是否生成client端使用的xml文件的标志设为truecfal = true;}// 判断单元格的内容是否为S,为S表示这一列要放入到生成的server端要使用的xml文件中} else if (cell.getStringCellValue().equals("S")) {// 添加单元格位置到snums中snums.add(i);// 判断是否是key列,如果是,表示要生成server端使用的xml文件if (keyNum == i) {// 将判断是否生成server端使用的xml文件的标志设为truesfal = true;}// 判断单元格的内容是否为A,为A表示这一列既要放入到生成的client端使用的xml文件中,又要放入到生成的server端要使用的xml文件中} else if (cell.getStringCellValue().equals("A")) {// 添加单元格位置到cnums中cnums.add(i);// 添加单元格位置到snums中snums.add(i);// 判断是否是key列,如果是,表示要生成client端和server端使用的xml文件if (keyNum == i) {// 将判断是否生成client端使用的xml文件的标志设为truecfal = true;// 将判断是否生成server端使用的xml文件的标志设为truesfal = true;}}}}}// 将要生成client端xml文件的位置信息放入到obj[0]obj[0] = cnums;// 将要生成server端xml文件的位置信息放入到obj[1]obj[1] = snums;// 将判断是否要生成client端xml文件的标志放入到obj[2]obj[2] = cfal;// 将判断是否要生成server端xml文件的标志放入到obj[3]obj[3] = sfal;// 返回这一行所有的信息return obj;}// 获取要打印到xml文件中的内容private String getOutputStr(List<String> nameList, List<String> annotationList, List<String> classList,String firstName, Sheet sheet, List<Integer> nums, String xmlDeclaration, boolean isServer) {// 声明一个StringBuilder,用来存放要打印到xml文件中的内容StringBuilder builder = new StringBuilder("");// 向builder中放入配置声明,包括版本号和编码类型builder.append(xmlDeclaration + " \n");// 向builder中放入注释的开始符号builder.append("<!-- ");// 向builder中放入换行符builder.append("\n");// 遍历位置信息for (Integer num : nums) {// 将该位置的字段说明放入到builder中builder.append(annotationList.get(num) + " ");}// 向builder中放入换行符builder.append("\n");// 遍历位置信息for (Integer num : nums) {// 将该位置的字段类型放入到builder中builder.append(classList.get(num) + " ");}// 向builder中放入换行符builder.append("\n");// 向builder中放入注释结束符和换行符builder.append("--> \n");// 向builder中放入标签开始符号builder.append("<");// 向builder中放入标签名称builder.append(firstName);// 向builder中放入标签结束符号builder.append(">");// 向builder中放入换行符builder.append("\n");// 遍历该sheet中从第四行开始的所有行,从第四行开始就是数据行了for (int i = 4; i <= sheet.getLastRowNum(); i++) {// 获取某一行Row row = sheet.getRow(i);// 判断这一行是否为空if (row != null) {// 获取本行的第一个单元格Cell cell1 = row.getCell(0);// 判断这个单元格是否为空,或者是空白的,或者是错误的,如果符合其中一种,我们就跳过此次循环if (cell1 == null || cell1.getCellType() == Cell.CELL_TYPE_BLANK|| cell1.getCellType() == Cell.CELL_TYPE_ERROR) {continue;}// 这里是向builder中添加数据标签的开始符,我这里用的是小写字母l,大家也可以换掉builder.append(" <l ");// 遍历所有要向xml中放入的数据列for (int j = 0; j < nums.size(); j++) {// 获取这一行中的某一列的单元格Cell cell = row.getCell(nums.get(j));// 判断单元格是否为空,或者空白,或者是错误的,如果符合其中一种,我们就跳过此次循环if (cell != null) {if (cell.getCellType() == Cell.CELL_TYPE_BLANK || cell.getCellType() == Cell.CELL_TYPE_ERROR) {continue;}// 判断生成的xml文件是否是server端使用的,如果是server端使用的,我们将他的属性名全部小写处理,// 如果大家不想这样做,可以去掉这个判断,只留下else里面的那一行代码if (isServer) {// 向builder中添加该列的属性名称,这里是对server端的处理,所以我进行了toLowerCase()处理builder.append(nameList.get(nums.get(j)).toLowerCase() + "=\"");} else {// 向builder中添加该列的属性名称,这里是对client端的处理builder.append(nameList.get(nums.get(j)) + "=\"");}// 判断该单元格是否是boolean类型if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {// 当该单元格的类型为boolean类型时,我们调用单元格的getBooleanCellValue()这个方法获取它的值,然后将该值放入builder中builder.append(cell.getBooleanCellValue() + "\" ");// 判断该单元格是否是公式类型} else if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {// 当该单元格的类型为公式类型时,我们调用单元格的getCellFormula()这个方法获取它的值,然后将该值放入builder中(这个获取到的是一个公式)builder.append(cell.getCellFormula() + "\" ");// 判断该单元格是否是数值类型} else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {// 当该单元格的类型为数值类型时,我们调用单元格的getNumericCellValue()这个方法获取它的值,然后将该值放入builder中// 这里因为我用到的数据都是整数型的,所有我将取到的值强转成了int,大家也可以去掉强转,就取原来的值就好builder.append((int) (cell.getNumericCellValue()) + "\" ");// 判断该单元格的类型是否是字符串类型} else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {// 当该单元格的类型为字符串类型时,我们调用单元格的getStringCellValue()这个方法获取它的值,然后将该值放入builder中builder.append(cell.getStringCellValue() + "\" ");}}}// 向builder中放入本条数据的结束符,以及换行符builder.append("/> \n");} else {continue;}}// 向builder中放入结束标签的开始符builder.append("</");// 向builder中放入结束标签的标签名builder.append(firstName);// 向builder中放入结束标签的结束符builder.append(">");// 返回我们要向xml中插入的内容return builder.toString();}// 将内容outputStr插入到文件xmlFile中private void writer(File xmlFile, String outputStr) throws IOException {// 判断该文件是否存在if (xmlFile.exists()) {// 如果存在,删除该文件xmlFile.delete();}// 创建该文件xmlFile.createNewFile();// 实例化一个输出流,该输出流输出的目标对象是xmlFile,输出时的编码格式为utf-8,这里大家可以根据自己的实际情况作修改OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(xmlFile), "utf-8");// 将outputStr写入到文本中writer.write(outputStr);// 关闭输出流writer.close();}}

config.properties配置文件中,有四个需要配置的数据:ExcelPath请配置你的excel所在的路径,ClientPath请配置你的client端生成的xml文件需要放置的目录,ServerPath请配置你的server端生成的xml文件需要放置的目录,xmlDeclaration请配置生成的xml中第一行的声明,其中的version和encoding请根据自己的需求填写,示例如下图:

源码及相关jar文件在github的下载地址:/yuchaozxc/ExcelToXml

源码及相关jar文件在csdn的下载地址:/detail/u013871927/9916745

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。