java实现控制台打印表格【自动生成表格例程】

java实现控制台打印表格【自动生成表格例程】

对于如下图的“学生成绩单”表格信息,如果用户有需求提取不同的字段列,只要传入报表参数和报表数据信息,本例程即可自动生成报表打印。

在这里插入图片描述
与C语言“汉字是双字节,ASCII码字符是单字节”不同;Java语言用双字节表示一个字符,无论是汉字还是ASCII码字符,Java字符串的长度单位也是双字节的。然而,通常情况,打印机的ASCII码字符只占一个字节长度,汉字则占两个字节长度。打印机的处理方式,与C语言是兼容的,但与Java语言不兼容。因此Java程序比C语言需要额外多做一些调整工作。

详细的程序代码如下:

public class AutoReport {
	private char[][] lineSign = { 
		{'┏','━','┳','┓'},{'┃',' ','┃','┃'},
		{'┣','━','╋','┫'},{'┗','━','┻','┛'}};
	/*** hLines[]数组共有4个StringBuilder(64),分别用于保存:
	* hLines[0] 表格头第一行表格线    "┏━━┳━━┓";
	* hLines[1] 表格头第二行字段名称行"┃名称┃名称┃";
	* hLines[2] 表格中间分隔行表格线  "┣━━╋━━┫";
	* hLines[3] 表格最后一行表格线    "┗━━┻━━┛"; ***/
	private StringBuilder[] hLines={null,null,null,null};
	 
	public AutoReport(ReportParam param,String[][]report) 
	{
		mkReportHead(param); //生成报表头
		prnReport(param,report); //打印报表
	}
	
	/***生成报表头的方法***/
	private void mkReportHead( ReportParam param ) {
		int len,k,fieldsNum;
		String fldName;
		
		int[] fields = param.fieldsSelected;
		String[] fieldNames = param.fieldsName;

		//初始化hLines[]
		for (int i = 0; i < hLines.length; i++) 
			hLines[i] = new StringBuilder(64);		
		
		/*** 处理表头、表尾及字段名行和中间分隔线行***/
		fieldsNum = param.fieldsSelected.length;//选定的字段个数
		for (int i = 0; i < fieldsNum; i++) 
		{//switch语句"0:"处理首字段;"1:"处理中间字段,"default:"处理末字段。
			if (i==0) k = 0; //每行第一个字段特殊处理。
			else if (i==fieldsNum-1) k = 99; //末字段,特殊处理。
			else k = 1;   //中间字段处理方法都一样。
			
			len = param.fieldsLen[i]; //第i个字段的长度
			//定制指定长度的表头字段名字符串
			fldName= getFixedLenString(fieldNames[(fields[i]-1)],len,'c');
			switch (k) {
			case 0:  //每行首字段的处理
				//追加制表符的每行行首字符,'┏'、'┃'、'┣'、'┗'
				hLines[0].append(lineSign[0][0]);  //表格头第一行
				hLines[1].append(lineSign[1][0]);  //表格字段名行
				hLines[2].append(lineSign[2][0]); //表格中间分隔行
				hLines[3].append(lineSign[3][0]);  //表格最后一行
				/*** 以上是每行的第一个字段特殊字符处理。***/
				
				/*** 以下是各字段相同处理部分***/
				for (int l = 0; l < len; l++) { //循环len次
					hLines[0].append(lineSign[0][1]);  //表格头第一行
					hLines[2].append(lineSign[2][1]);  //表格中间分隔行
					hLines[3].append(lineSign[3][1]);  //表格最后一行
				}
				//表格字段名行 hLines[1]:设置字段名称。与上面三行处理不同
				hLines[1].append(fldName);
				break;

			case 1:   //每行的中间字段的处理
				//追加制表符的每个字段间制表符,如'┳'、'┃'、'╋'、'┻'等
				hLines[0].append(lineSign[0][2]);  //表格头第一行
				hLines[1].append(lineSign[1][2]);  //表格字段名称行
				hLines[2].append(lineSign[2][2]);  //表格中间分隔行
				hLines[3].append(lineSign[3][2]);  //表格最后一行
				
				/*** 以下是各字段相同处理部分***/
				for (int l = 0; l < len; l++) { //循环len次
					hLines[0].append(lineSign[0][1]);  //表格头第一行
					hLines[2].append(lineSign[2][1]);  //表格中间分隔行
					hLines[3].append(lineSign[3][1]);  //表格最后一行
				}
				//表格字段名行 hLines[1]:设置字段名称。与上面三行处理不同
				hLines[1].append(fldName);
				break;

			default:  //每行的最后一个字段的处理
				//追加制表符的每个字段间制表符,如'┳'、'┃'、'╋'、'┻'等
				hLines[0].append(lineSign[0][2]);  //表格头第一行
				hLines[1].append(lineSign[1][2]);  //表格字段名称行
				hLines[2].append(lineSign[2][2]);  //表格中间分隔行
				hLines[3].append(lineSign[3][2]);  //表格最后一行
				
				/*** 以下是各字段相同处理部分***/
				for (int l = 0; l < len; l++) { //循环len次
					hLines[0].append(lineSign[0][1]);  //表格头第一行
					hLines[2].append(lineSign[2][1]);  //表格中间分隔行
					hLines[3].append(lineSign[3][1]);  //表格最后一行
				}
				//表格字段名行 hLines[1]:设置字段名称。与上面三行处理不同
				hLines[1].append(fldName);
				/*** 以上的处理是各字段相同处理部分***/
				
				/*** 下面的处理是每行最后一个字段特殊处理。***/
				//追加表格的行结束字符:'┓'、'┃'、'┫'、'┛'
				hLines[0].append(lineSign[0][3]);  //表格头第一行
				hLines[1].append(lineSign[1][3]);  //表格字段名行
				hLines[2].append(lineSign[2][3]); //表格中间分隔行
				hLines[3].append(lineSign[3][3]);  //表格最后一行
				break;
			}
		}
	}
	
	/***打印报表的方法***/
	private void prnReport(ReportParam param,String[][]report) {
		int len,fieldsNum;
		char type;
		String fixLenStr;
		
		//打印表格表头
		System.out.println(hLines[0].toString());
		System.out.println(hLines[1].toString());
		
		/***处理报表数据行***/
		int[] fields = param.fieldsSelected;
		fieldsNum = param.fieldsSelected.length;//选定的字段个数
		StringBuilder dataLine = new StringBuilder(64);
		//循环打印表格中间分隔行和数据行
		for (int n = 0; n < report.length; n++) {
			System.out.println(hLines[2].toString()); //打印表格中间分隔行
			dataLine.delete(0, dataLine.capacity()); //清空dataLine数据
			for (int i = 0; i < fieldsNum; i++) { //每行中的各个字段的处理
				dataLine.append(lineSign[1][0]); //插入表格字符
				
				//定制指定长度的字符串
				len = param.fieldsLen[i]; //第i个字段的长度
				type = param.fieldsType[i];//第i个字段的类型
				fixLenStr = getFixedLenString(report[n][fields[i]-1],len,type);
				dataLine.append(fixLenStr);
			}
			dataLine.append(lineSign[1][3]); //插入行尾表格字符
			System.out.println(dataLine.toString());
		}
		
		//打印表格最后一行: 制表符表格封底线行。
		System.out.println(hLines[3].toString());
	}
	
	/*** 定制指定长度的字符串方法
	 * @param str 字段信息;
	 * @param len 字段列指定的打印长度;
	 * @param type 数据类型。c左对齐;n右对齐;
	 * @return 指定长度的字符串。
	 * ***/
	public String getFixedLenString(String str,int len, char type) 
	{
		if (str==null||str.length()==0) str="";
		int num = getASCIICharCount(str);//单字节字符数
/***计算需要补空格的长度***/
		int k = 2*(len-str.length())+num;//需要补空格的长度
		StringBuilder sBuilder = new StringBuilder(64);
		/***字符串小于指定打印长度的,用空格(' ')作为填充字符***/
		if (type=='c') { //左对齐,右补空格
			sBuilder.append(str);
			for (int i = 0; i < k; i++) sBuilder.append(' ');
		} 
		else {  //右对齐,左补空格
			for (int i = 0; i < k; i++) sBuilder.append(' ');
			sBuilder.append(str);
		}
		return sBuilder.toString();
	}
	
    /* 计算字符串中单字节字符出现的次数
     * @param str
     * @return
     ******/
    public int getASCIICharCount(String str) {
        if (str == null) {  return 0;  }
        //非ASCII码字符的正则表达式
        String reg = "[^\\x00-\\x7f]"; 
        return str.replaceAll(reg, "").length();
    }
	
	public static void main(String[] args) {
		int[] fieldsLen = {4,2,2,2,2,2,2,2};
		char[] fieldsType = {'c','c','n','n','n','n','n','n'};
		String[] fieldNames = {"姓名","学号","语文","数学","英语","物理","生物","历史"};

		String[][] report = {
			{"常昊","0801","88","100","68","85","80","65"},
			{"刘国梁","0802","76","75","89","76","88","90"},
			{"常遇春","0601","90","68","78","86","92","70"},
			{"戚继光","0602","82","86","88","75","78","86"}};
		
		//选定出报表的字段,用序号表示: 1 代表字段“姓名”,4代表字段“数学”,依次类推。
		//选择前5个字段:"姓名","学号","语文","数学","英语"
		int[] fields01 = {1,2,3,4,5};
		int[] fields02 = {1,2,3,4,5,6,7,8}; //选择所有字段。
		int[] fields03 = {1,2,3,4,6,8}; //随机选择字段。
		
		//参数设定
		ReportParam param = new ReportParam();
		param.rowsInPage = 3; //重新设定每页行数
		param.fieldsLen =fieldsLen;
		param.fieldsType = fieldsType;
		param.fieldsName = fieldNames;
		
		param.fieldsSelected = fields01;
		System.out.println("   学  生  成  绩  单01");
		new AutoReport(param, report);
		param.fieldsSelected = fields02;
		System.out.println("   学  生  成  绩  单02");
		new AutoReport(param, report);
		param.fieldsSelected = fields03;
		System.out.println("   学  生  成  绩  单03");
		new AutoReport(param, report);
	}
}

class ReportParam { //报表参数
	String[] fieldsName; //所有字段名称
	//字段类型:c表示文本型;n表示数值型
	char[] fieldsType; //所有字段的类型
	int[] fieldsLen; //所有字段的长度
	int[] fieldsSelected;//选定出报表的字段
	//每页行数:可按需重新设定
	int rowsInPage = 28; //每页行数默认值是28
}   

程序未进行分页处理,有兴趣的可自行增加分页功能。程序的运行效果如下:(控制台的显示有点问题,对得不是很齐,这是把控制台显示结果复制到UltraEdit编辑器的效果图)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值