君辰的gravatar头像
君辰 2015-04-30 17:15:19

apache poi读取excel,.xlsx格式如何统计手机号的数量?

网上找的读取方法,可用。但是我实际业务需要返回一个int类型的值,就是excle的有效数据,这个数据是手机号。我需要他返回给我有效的手机号数量,我解决不了,求大神。我不要手机号,是手机号的数量...

package com.ccop.common.util.poi;

import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * XSSF and SAX (Event API)
 */
public abstract class XxlsAbstract extends DefaultHandler {
	private SharedStringsTable sst;
	private String lastContents;
	private boolean nextIsString;

	private int sheetIndex = -1;
	private List<String> rowlist = new ArrayList<String>();
	private int curRow = 0;		//当前行
	private int curCol = 0;		//当前列索引
	private int preCol = 0;		//上一列列索引
	private int titleRow = 0;	//标题行,一般情况下为0
	private int rowsize = 0;	//列数
	
	//excel记录行操作方法,以行索引和行元素列表为参数,对一行元素进行操作,元素为String类型
//	public abstract void optRows(int curRow, List<String> rowlist) throws SQLException ;
	
	//excel记录行操作方法,以sheet索引,行索引和行元素列表为参数,对sheet的一行元素进行操作,元素为String类型
	public abstract void optRows(int sheetIndex,int curRow, List<String> rowlist) throws SQLException;
	
	//只遍历一个sheet,其中sheetId为要遍历的sheet索引,从1开始,1-3
	public void processOneSheet(String filename,int sheetId) throws Exception {
		OPCPackage pkg = OPCPackage.open(filename);
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();
		XMLReader parser = fetchSheetParser(sst);
		// rId2 found by processing the Workbook
		// 根据 rId# 或 rSheet# 查找sheet
		InputStream sheet2 = r.getSheet("rId"+sheetId);
		sheetIndex++;
		InputSource sheetSource = new InputSource(sheet2);
		parser.parse(sheetSource);
		sheet2.close();
		pkg.close();
	}

	/**
	 * 遍历 excel 文件
	 */
	public void process(String filename) throws Exception {
		OPCPackage pkg = OPCPackage.open(filename);
		XSSFReader r = new XSSFReader(pkg);
		SharedStringsTable sst = r.getSharedStringsTable();

		XMLReader parser = fetchSheetParser(sst);

		Iterator<InputStream> sheets = r.getSheetsData();
		while (sheets.hasNext()) {
			curRow = 0;
			sheetIndex++;
			InputStream sheet = sheets.next();
			InputSource sheetSource = new InputSource(sheet);
			parser.parse(sheetSource);
			sheet.close();
		}
		pkg.close();
	}

	public XMLReader fetchSheetParser(SharedStringsTable sst)
			throws SAXException {
		XMLReader parser = XMLReaderFactory
				.createXMLReader();
		this.sst = sst;
		parser.setContentHandler(this);
		return parser;
	}

	public void startElement(String uri, String localName, String name,
			Attributes attributes) throws SAXException {
		// c => 单元格
		if (name.equals("c")) {
			// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
			String cellType = attributes.getValue("t");
			String rowStr = attributes.getValue("r");
			curCol = this.getRowIndex(rowStr);
			if (cellType != null && cellType.equals("s")) {
				nextIsString = true;
			} else {
				nextIsString = false;
			}
		}
		// 置空
		lastContents = "";
	}

	public void endElement(String uri, String localName, String name)
			throws SAXException {
		// 根据SST的索引值的到单元格的真正要存储的字符串
		// 这时characters()方法可能会被调用多次
		if (nextIsString) {
			try {
				int idx = Integer.parseInt(lastContents);
				lastContents = new XSSFRichTextString(sst.getEntryAt(idx))
						.toString();
			} catch (Exception e) {

			}
		}

		// v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
		// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
		if (name.equals("v")) {
			String value = lastContents.trim();
			value = value.equals("")?null:value;
			int cols = curCol-preCol;
			if (cols>1){
				for (int i = 0;i < cols-1;i++){
					rowlist.add(preCol,null);
				}
			}
			preCol = curCol;
			rowlist.add(curCol-1, value);
		}else {
			//如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
			if (name.equals("row")) {
				int tmpCols = rowlist.size();
				if(curRow>this.titleRow && tmpCols<this.rowsize){
					for (int i = 0;i < this.rowsize-tmpCols;i++){
						rowlist.add(rowlist.size(), null);
					}
				}
				try {
					int a=0;
					optRows(sheetIndex,curRow,rowlist);
				} catch (SQLException e) {
					e.printStackTrace();
				}
				if(curRow==this.titleRow){
					this.rowsize = rowlist.size();
				}
				rowlist.clear();
				curRow++;
				curCol = 0;
				preCol = 0;
			}
		}
	}

	public void characters(char[] ch, int start, int length)
			throws SAXException {
		//得到单元格内容的值
		lastContents += new String(ch, start, length);
	}
	
	//得到列索引,每一列c元素的r属性构成为字母加数字的形式,字母组合为列索引,数字组合为行索引,
	//如AB45,表示为第(A-A+1)*26+(B-A+1)*26列,45行
	public int getRowIndex(String rowStr){
		rowStr = rowStr.replaceAll("[^A-Z]", "");
		byte[] rowAbc = rowStr.getBytes();
		int len = rowAbc.length;
		float num = 0;
		for (int i=0;i<len;i++){
			num += (rowAbc[i]-'A'+1)*Math.pow(26,len-i-1 );
		}
		return (int) num;
	}

	public int getTitleRow() {
		return titleRow;
	}

	public void setTitleRow(int titleRow) {
		this.titleRow = titleRow;
	}
}
/**
 * @author zhujl
 *
 * 2015-4-30
 */
package com.ccop.common.util.poi;

import java.sql.SQLException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



public class XxlsPrint extends XxlsAbstract {  
    public static void main(String[] args) throws Exception {  
        XxlsPrint howto = new XxlsPrint();  
        howto.processOneSheet("E:\\短信平台.xlsx20150410155355319.xlsx",1); 
    }
    
	@Override
	public void optRows(int sheetIndex, int curRow, List<String> rowlist)
			throws SQLException {
			int a=0;
		 	Pattern p = null;  
	        Matcher m = null;  
	        boolean b = false;   
	        p = Pattern.compile("^[1][3,4,5,8][0-9]{9}$"); // 验证手机号  
	        for (int i = 0; i < rowlist.size(); i++) {  
			  String ss=rowlist.get(i);
			  m = p.matcher(ss);  
			  b = m.matches(); 
			  if(b){
				  //如果是手机号
			  }
			 }
	}  
}  
所有回答列表(5)
遇见,的gravatar头像
遇见,  LV36 2015年4月30日

手机号重复是统计1个还是多个。

允许重复用list 否则用set

glyph的gravatar头像
glyph  LV10 2015年5月1日

这个不应该难吧。就是读取然后统计。你读取后正则表达式判断,然后存到到HashMap中,最后size()不就oK了。

liziwei882的gravatar头像
liziwei882  LV5 2015年5月6日

直接用list就应该可以了吧,重复的不都是一个嘛。简单就是获取这个表格有多少行 然后对应那行去重。

肥波先生的gravatar头像
肥波先生  LV12 2015年5月8日
p = Pattern.compile("^[1][3,4,5,8][0-9]{9}$"); // 验证手机号 
29             for (int i = 0; i < rowlist.size(); i++) { 
30               String ss=rowlist.get(i);
31               m = p.matcher(ss); 
32               b = m.matches();
33               if(b){
34                   //如果是手机号
35               }
36              }

 

你都已经得到如果是手机号码了,既然要取有效的再次去重就得到数量了嘛,将结果返回还不行哦

君辰的gravatar头像
君辰  LV7 2015年5月10日

判断手机号我知道,不允许重复。他这个读某个单元格的值是触发的2个事件,我无法定义一个全局变量。

顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友