Excel列名与数字的相互转换
来源:互联网 发布:模特兼职知乎 编辑:程序博客网 时间:2024/05/01 00:34
public static class Excel2007Index { private static int nextDatum = 17576; private static int[] baseNum = new int[] { 1, 26, 676 }; private static List<long> baseNumList = new List<long>(new long[]{1, 26, 676}); private static System.Text.RegularExpressions.Regex matchCStart = new System.Text.RegularExpressions.Regex("^[A-Z]{1,3}$", System.Text.RegularExpressions.RegexOptions.Compiled); private delegate string CalColumnRangeDelegate(int columnIndex); private static CalColumnRangeDelegate[] CalColumnRange = new CalColumnRangeDelegate[] { CalColumnRange1, CalColumnRange2, CalColumnRange3 }; /// <summary> /// 从指定Excel的列序号获得索引值(1 表示为 A)。 /// </summary> /// <param name="columnIndex">从1开始的列序号。</param> /// <returns></returns> public static string GetAnyColumnRangeFromIndex(int columnIndex) { if (columnIndex <= 0) throw new ArgumentOutOfRangeException("columnIndex"); return CalColumnRange4(columnIndex); } /// <summary> /// 从指定Excel的列序号获得索引值(A 表示为 1)。 /// </summary> /// <param name="columnIndex">从A开始的列序号。</param> /// <returns></returns> public static long GetAnyColumnIndexFromRange(string columnRange) { columnRange = columnRange.ToUpper(Excel2007Workbook.invariantCulture); if (!System.Text.RegularExpressions.Regex.IsMatch(columnRange, "[A-Z]{1}")) throw new ArgumentOutOfRangeException("columnRange"); UpdateBaseNum(columnRange); long sum = 0, multi = 0; int i = columnRange.Length - 1; foreach (var ch in columnRange) { multi = (int)ch - 64; multi = multi * baseNumList[i]; sum += multi; i--; } return sum; } /// <summary> /// 从指定Excel的列序号获得索引值(A 表示为 1)。 /// </summary> /// <param name="columnRange">从A开始的列序号,最大不超过ZZZ(18278)。</param> /// <returns></returns> public static int GetColumnIndexFromRange(string columnRange) { columnRange = columnRange.ToUpper(Excel2007Workbook.invariantCulture); if (!matchCStart.IsMatch(columnRange)) throw new ArgumentException("", "columnRange"); int sum = 0, multi = 0; int i = columnRange.Length - 1; foreach (var ch in columnRange) { multi = (int)ch - 64; multi = multi * baseNum[i]; sum += multi; i--; } return sum; } /// <summary> /// 从指定索引值获得Excel的列序号表示(1 表示为 A)。 /// </summary> /// <param name="columnIndex">从1开始不大于17576的列索引。</param> /// <returns></returns> public static string GetColumnRangeFromIndex(int columnIndex) { if (columnIndex <= 0 || columnIndex > nextDatum) throw new ArgumentOutOfRangeException("columnIndex"); int c = 0; if (columnIndex != 1) c = (int)Math.Log(columnIndex - 1, 26); return CalColumnRange[c](columnIndex); } /// <summary> /// 适用于小于等于26列的Excel列算法。 /// </summary> /// <param name="columnIndex">从1开始的列索引。</param> /// <returns></returns> private static string CalColumnRange1(int columnIndex) { return ((char)(columnIndex + 64)).ToString(); } /// <summary> /// 适用于大于26列小于等于676列的Excel列算法。 /// </summary> /// <param name="columnIndex">从1开始的列索引。</param> /// <returns></returns> private static string CalColumnRange2(int columnIndex) { // resuide 余数,quotient商 int residue = 0, quotient = 0; StringBuilder str = new StringBuilder(2); quotient = Math.DivRem(columnIndex, baseNum[1], out residue); if (residue == 0) { quotient--; residue = 26; } str.Append((char)(quotient + 64)); str.Append((char)(residue + 64)); return str.ToString(); } /// <summary> /// 适用于大于676列小于等于17576列的Excel列算法。 /// </summary> /// <param name="columnIndex">从1开始的列索引。</param> /// <returns></returns> private static string CalColumnRange3(int columnIndex) { // resuide 余数,quotient商 int residue = 0, quotient = 0; StringBuilder str = new StringBuilder(3); for (int i = 2; i >= 0; i--) { quotient = Math.DivRem(columnIndex, baseNum[i], out residue); if (residue == 0 && i != 0) { quotient--; residue = baseNum[i]; } str.Append((char)(quotient + 64)); columnIndex = residue; } return str.ToString(); } /// <summary> /// 适用于有可能超出17576列的Excel列算法。 /// </summary> /// <param name="columnIndex">从1开始的列索引。</param> /// <returns></returns> private static string CalColumnRange4(int columnIndex) { if(columnIndex <=0) throw new ArgumentOutOfRangeException("columnIndex"); UpdateBaseNum(columnIndex); // resuide 余数,quotient商 int residue = 0, quotient = 0; StringBuilder str = new StringBuilder(baseNum.Length); for (int i = str.Length - 1; i >= 0; i--) { quotient = Math.DivRem(columnIndex, (int)baseNumList[i], out residue); if (residue == 0 && i != 0) { quotient--; residue = (int)baseNumList[i]; } str.Append((char)(quotient + 64)); columnIndex = residue; } return str.ToString(); } /// <summary> /// 当给定值大于所能计算的最大范围时,更新baseNumList列表。 /// </summary> /// <param name="columnIndex">从1开始的列索引</param> private static void UpdateBaseNum(int columnIndex) { while (columnIndex > nextDatum) { baseNumList.Add(nextDatum); nextDatum *= 26; } } /// <summary> /// 当给定列序号大于所能计算的最大范围时,更新baseNumList列表。 /// </summary> /// <param name="columnRange">从A开始的列序号。</param> private static void UpdateBaseNum(string columnRange) { for (int i = baseNumList.Count - 1; i < columnRange.Length; i++) { baseNumList.Add(nextDatum); nextDatum *= 26; } } }