用JS自制表格软件玩数据4. 行列计数器的实现

Posted 妇男主任

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JS自制表格软件玩数据4. 行列计数器的实现相关的知识,希望对你有一定的参考价值。

渲染单元格

当写完本系列后,我会把源代码分享出来给大家。本课程也会持续更新与矫正。欢迎留言指正!

前面已经设计了一个底层渲染类,现在准备在这个底层类的基础上,构建一个渲染单元格的模块。

列计数器

通常在 Excel 表格中,我们会看到横向的标尺使用了:A,B,C,D之类的字母作为标记。

原理

字母的显示,一般都是使用了ASCII码进行表示的,所以,大写字母的 A-Z 是从 65 开始的,到 90 结束。

二进制十进制十六进制缩写/字符解释
00000000000 NUL(null)空字符
00000001101SOH(start of headling)标题开始
00000010202STX (start of text)正文开始
00000011303ETX (end of text)正文结束
00000100404EOT (end of transmission)传输结束
00000101505ENQ (enquiry)请求
00000110606ACK (acknowledge)收到通知
00000111707BEL (bell)响铃
00001000808BS (backspace)退格
000010019 09HT (horizontal tab)水平制表符
0000101010 0A LF (NL line feed, new line)换行键
0000101111 0B VT (vertical tab)垂直制表符
0000110012 0C FF (NP form feed, new page)换页键
00001101130D CR (carriage return) 回车键
00001110140E SO (shift out)不用切换
00001111150F SI (shift in)启用切换
0001000016 10DLE (data link escape) 数据链路转义
000100011711 DC1 (device control 1) 设备控制1
000100101812 DC2 (device control 2)设备控制2
0001001119 13DC3 (device control 3) 设备控制3
000101002014 DC4 (device control 4)设备控制4
000101012115 NAK (negative acknowledge) 拒绝接收
000101102216 SYN (synchronous idle) 同步空闲
0001011123 17ETB (end of trans. block)传输块结束
0001100024 18CAN (cancel) 取消
0001100125 19EM (end of medium)介质中断
0001101026 1ASUB (substitute)替补
0001101127 1BESC (escape) 溢出
0001110028 1CFS (file separator) 文件分割符
0001110129 1DGS (group separator) 分组符
0001111030 1E RS (record separator) 记录分离符
0001111131 1FUS (unit separator)单元分隔符
0010000032 20(space)空格
0010000133 21 ! 
001000103422 " 
0010001135 23# 
0010010036 24$ 
0010010137 25% 
0010011038 26& 
0010011139 27 ' 
0010100040 28( 
001010014129) 
0010101042 2A* 
00101011432B+ 
0010110044 2C , 
0010110145 2D- 
0010111046 2E . 
0010111147 2F/  
0011000048 300 
0011000149 311  
0011001050 32 2 
0011001151 333  
0011010052 34 4 
0011010153 355  
0011011054366 
0011011155 37 7  
0011100056 388  
0011100157 39 9 
0011101058 3A:  
00111011593B; 
0011110060 3C<  
00111101613D= 
0011111062 3E>  
0011111163 3F ? 
0100000064 40@  
010000016541A 
0100001066 42 B  
010000116743C 
0100010068 44 D  
010001016945E 
010001107046 F 
010001117147G 
0100100072 48H  
010010017349I 
0100101074 4AJ  
01001011754BK 
0100110076 4C L  
01001101774DM 
0100111078 4EN  
01001111794FO 
0101000080 50P  
010100018151Q 
010100108252 R 
010100118353S 
0101010084 54T  
0101010185 55 U 
0101011086 56V  
0101011187 57W 
0101100088 58X  
010110018959 Y 
0101101090 5AZ  
0101101191 5B[  
01011100925C\\ 
0101110193 5D]  
01011110945E ^ 
0101111195 5F_ 
0110000096 60`  
011000019761 a 
0110001098 62b  
0110001199 63c  
0110010010064d 
01100101101 65e  
01100110102 66f 
01100111103 67g  
01101000104 68 h 
01101001105 69i  
011010101066Aj 
01101011107 6Bk  
01101100108 6C l 
01101101109 6D m 
011011101106En 
01101111111 6Fo  
01110000112 70 p 
01110001113 71q  
01110010114 72 r 
01110011115 73s  
01110100116 74 t 
01110101117 75 u 
01110110118 76v 
01110111119 77w  
01111000120 78x 
01111001121 79y  
01111010122 7A z 
01111011123 7B 
01111100124 7C| 
01111101125 7D 
01111110126 7E ~ 
01111111127 7F DEL (delete)删除

这个就要做一个表格坐标计数器来做统计。

步进器

首先设计一个步进器:

/**
* @property Function excel_Row_Increase 行移动定位
* @param String chr 例如:A1
* @param String num 例如:步进
* @returns Array 返回字符串数组,["A","1"]
*/
excel_Row_Increase(chr,num)
	this.caculate = function(chr,num)
		var carry = num; // 进位标志
		let temp = chr.split("");
		var count = temp.length-1;
		while(!(count < 0)) 
			let code = this.charmap[temp[count]] + carry;
			carry = 0;

			if (code > 64 && code < 91)
				temp[count] = String.fromCharCode(code);
			

			while(code < 65)
				carry--;
				code = code + 26;
				if(code > 64)
					temp[count] = String.fromCharCode(code);
					break;
				
			

			while(code > 90)
				carry++;
				code = code - 26;
				if(code < 91)
					temp[count] = String.fromCharCode(code);
					break;
				
			
			count--;
		
		var chr = temp.join("");
		if(chr == "A" && carry < 0)
			return 
				"carry":0,
				"char": chr
			
		else
			return 
				"carry":carry,
				"char":chr
			
		
	

	var result = this.caculate(chr,num);
	var ttt;
	while(result["carry"]!=0)
		ttt = this.caculate("A",--result["carry"]);
		result["char"] = ttt["char"]+result["char"];
		result["carry"] = ttt["carry"];
	
	return result["char"];


字符的运算表

接着,使用步进器创建了一个字符的运算表,这样它就可以快速运算了。

/**
	* @property Function setcaculatemap 创建字母运算表
	* @returns NaN 无返回
	*/
	setcaculatemap()
		var begin = "A";
		var mapsize = this.mapsize;
		this.caculatemap = [""];
		
		while(mapsize)
			this.caculatemap.push(begin);
			var begin = this.excel_Row_Increase(begin,1)
			mapsize--;
		
	

源码

直接上全部代码:

/**
 * 字符转编码
 */

class charcode
	/**
	* 创建字符映射集
	*/
	constructor()
		this.charmap = ;
		var ord = 65;
		var ordmax = ord+26;
		while(ord < ordmax)
			this.charmap[String.fromCharCode(ord)] = ord;
			ord++;
		
		ord = 65+32;
		ordmax = ord+26;
		while(ord < ordmax)
			this.charmap[String.fromCharCode(ord)] = ord-32;
			ord++;
		
		this.caculatemap = [];
		this.mapsize = 20;
		this.setcaculatemap();
		// console.log(this.caculatemap);
		
		this.RowColcountMap = ;
	

	/**
	* @property Function setcaculatemap 创建字母运算表
	* @returns NaN 无返回
	*/
	setcaculatemap()
		var begin = "A";
		var mapsize = this.mapsize;
		this.caculatemap = [""];
		
		while(mapsize)
			this.caculatemap.push(begin);
			var begin = this.excel_Row_Increase(begin,1)
			mapsize--;
		
	
	
	/**
	* @property Function countelementToindex 计算坐标在单元格的位置
	* @param String x 输入编码,表格的横向尺寸
	* @param Number y 输入编码,表格的纵向尺寸
	* @param String elementIndex 输入编码
	* @returns Number 返回数字坐标
	*/
	countelementToindex(x,y,elementIndex)
		var count = this.CharToDecimal(x); // 字符转坐标
		var titlecount = count+y+1; // 标头长度
		// var max = count*(y); // 表格总尺寸
		var ttt = this.getRowCol(elementIndex); // 分离行列
		var currentX = this.caculatemap.indexOf(ttt[0]) // 获取行的坐标

		return count*(ttt[1]-1)+currentX+titlecount-1;
	

	/**
	* @property Function countindexToelement 将当前位置转化为坐标
	* @param String x 输入编码,表格的横向尺寸
	* @param Number y 输入编码,表格的纵向尺寸
	* @param Number index 输入位置
	* @returns Number 返回坐标
	*/
	countindexToelement(x,y,index)
		var count = this.CharToDecimal(x); // 字符转坐标,获得横向的宽度
		var titlecount = count+y+1; // 标头总数量
		var max = count*(y); // 表格总尺寸
		
		var A = titlecount; // 获取A的位置
		var ttt = index-A+1; // 获取输入框的总个数
		if(ttt >= count)
			var mod = ttt%count;
			if(mod != 0)
				return this.caculatemap[mod]+(parseInt(ttt/count)+1)
			else
				return this.caculatemap[count]+(parseInt(ttt/count))
			
		else
			return this.caculatemap[ttt]+1
		
	

	/**
	* @property Function CHR 编码转字符
	* @param Number ord 输入编码
	* @returns String 返回字符编码
	*/
	CHR(ord)
		return String.fromCharCode(ord);
	

	/**
	* @property Function ORD 字符转编码
	* @param String chr 输入字符串
	* @returns Number 返回字符编码
	*/
	ORD(chr)
		return chr.charCodeAt(0);
	

	/**
	* @property Function CharToDecimal 进制字符转十进制
	* @param String chr 输入字符串
	* @returns Number 返回十进制编码
	*/
	CharToDecimal(Char)
		var Decimal = this.caculatemap.indexOf(Char);
		while(Decimal < 0)
			this.mapsize = this.mapsize*10;
			this.setcaculatemap();
			Decimal = this.caculatemap.indexOf(Char);
		
		return Decimal;
	

	/**
	* @property Function DecimalToChar 十进制转字符进制
	* @param Number Decimal 输入十进制
	* @returns String 返回字符进制
	*/
	DecimalToChar(Decimal)
		var length = this.caculatemap.length-1;
		var balance = Decimal - length;
		if(balance > 0)
			this.mapsize = this.mapsize+balance+1;
			this.setcaculatemap();
		
		return this.caculatemap[Decimal];
	

	/**
	* @property Function CharAdd 字母相加
	* @param String CharA 输入字符
	* @param String CharB 输入字符
	* @returns Number 返回十进制编码
	*/
	CharAdd(CharA,CharB) // 字母相加
		return this.CharToDecimal(CharA)+this.CharToDecimal(CharB)
	
	
	/**
	* @property Function CharMinus 字母相减
	* @param String CharA 输入字符
	* @param String CharB 输入字符
	* @returns Number 返回十进制编码
	*/
	CharMinus(CharA,CharB) // 字母相减
		return this.CharToDecimal(CharA)-this.CharToDecimal(CharB)
	

	/**
	* @property Function getRowCol 从行列串中分离出行与列
	* @param String RC 行列串,例如:A1
	* @returns Array 返回字符串数组,["A","1"]
	*/
	getRowCol(RC)
		var Row = [];
		var Col = [];

		for(var i in RC)
			this.charmap.hasOwnProperty(RC[i])?Col.push(RC[i]):Row.push(RC[i]);
		
		return [Col.join(""),Row.join("")]
	

	/**
	* @property Function setRectanglecorner 设置四个坐标角落
	* @param String a 坐标,例如:A1
	* @param String b 坐标,例如:B2
	* @returns Array 返回字符串数组,["A","1"]
	*/
	setRectanglecorner(a,b)
		var RSort = [];
		var CSort = [];
		var aRC = this.getRowCol(a);
		var bRC = this.getRowCol(b);
		var Rdistance = this.CharMinus(bRC[0],aRC[0]);
		if(Rdistance < 0)
			RSort = [bRC[0],aRC[0]];
		else
			RSort = [aRC[0],bRC[0]];
		
		if(bRC[1]-aRC[1]<0)
			CSort = [bRC[1],aRC[1]];
		else
			CSort = [aRC[1],bRC[1]];
		
		
		return [[RSort[0],CSort[0]],[RSort[1],CSort[1]]]
	

	/**
	* @property Function GetRectangle 计算出框选区域
	* @param String from 行列串,例如:A1
	* @param String to 行列串,例如:B2
	* @returns Array 返回字符串数组,["A","1"]
	*/
	GetRectangle(from,to)
		var t = this.setRectanglecorner(from,to);
		var fromRC = t[0];
		var toRC = t[1];

		var distance =
		[
			this.CharMinus(toRC[0],fromRC[0]),
			toRC[1]-fromRC[1]
		]
		// console.log(fromRC);
		// console.log(toRC);
		// console.log(distance);
		var Rowcount = parseInt(fromRC[1])+distance[1]+1;
		var ColList = this.caculatemap.slice(this.CharToDecimal(fromRC[0]),this.CharToDecimal(fromRC[0])+distance[0]+1);
		var length = ColList.length;
		var Rectangle = [];
		for(var i = 0;i<length;i++)
			for(var j = fromRC[1];j<Rowcount;j++)
				Rectangle.push(ColList[i]+j);
			
		
		return 
			"Rowlength":Rowcount-parseInt(fromRC[1]),
			"Collength":length,
			"Rectangle":Rectangle
		;
	

	/**
	* @property Function excel_Row_Increase 行移动定位
	* @param String chr 例如:A1
	* @param String num 例如:步进
	* @returns Array 返回字符串数组,["A","1"]
	*/
	excel_Row_Increase(chr,num以上是关于用JS自制表格软件玩数据4. 行列计数器的实现的主要内容,如果未能解决你的问题,请参考以下文章

用JS自制表格软件玩数据5. 渲染出整个Excel单元格

用JS自制表格软件玩数据5. 渲染出整个Excel单元格

用JS自制表格软件玩数据7. 设计常用的样式功能与单元格合并

用JS自制表格软件玩数据7. 设计常用的样式功能与单元格合并

用JS自制表格软件玩数据6. 单元格的多选

用JS自制表格软件玩数据11. 虚拟机电路仿真加法运算器