C# Input Value how to validate from A to ZZZ - c#

Input Value can be from A to ZZZ (only alphabetical, no numeric characters) how can I validate a from and to field.
Where the input can be A or AA or AAA
B > A
BB > A
BBB > A
BBB < B
BBB < BB
DD > C
but then D should be < CC fails because it is not a lexicographical order
I was thinking check the length first because if the from length is less than to length then it will always be less. If equal in length then an alphabetical check. Then I come unstuck.
Not simple lexicographical order because three possiable groups single, double, triple chars single group lower than double and triple group and double lower than triple group not just alphabetical.

have you thought about using a regexp? \b[A-Z]{1,3}\b

You can do the following: Imagine the String AAA as a number, saying A*26^2 + A*26^1 + A*26^0
(Base 26, because there are that much letters)
Split the String, Cast values A to Z to 1 to 26 (WhiteSpace in front = 0) and you are done:
A = 0*26^2 + 0*26^1 + 1*26^0 => 1
B = 2 => 2
...
Z = 26 => 26
AA = 1 * 26^1 + 1 => 27
...
ZZ = 26*26^1 + 26 = 702
...
ZZZ = 26*26^2 + 26*26^1 + 26 => 18278
wrap it Like
public int LetterCodeToInt(String LetterCode)
{
//fill up whitespaces in front.
String s = LetterCode.PadLeft(3, '_').ToUpper();
int value = 0;
int k = s.Length -1;
for (int i = 0; i < s.Length; i++)
{
if (s[i] != '_')
{
//ASCII "A" is 65, subtract 64 to make it "1"
value += (((int)s[i]) - 64) * Convert.ToInt32(Math.Pow(26, k));
}
k--;
}
return value;
}
and you can do:
if (LetterCodeToInt("AAA") > LetterCodeToInt("AZ")){
}

string from = "BB";
string to = "AAA";
bool valid = string.Compare(from, to) < 0; // false
So it works already in lexicographical order. Demo

You're on the right track. Create a custom comparer that checks the length first. For example:
public class MyComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x.Length < y.Length) return -1;
if (x.Length > y.Length) return 1;
return Comparer.Default.Compare(x, y);
}
}

Related

C# Finding "connected" permutations

I'm working on a dictionary table and required to find out all possible combination of characters in a word. Thanks to https://codereview.stackexchange.com/questions/28248/implement-a-function-that-prints-all-possible-combinations-of-the-characters-in , I got below working so far:
public List<string> findAllOccurance(string str)
{
var results = from e in Range(0, BigInteger.Pow(2, str.Length))
let p =
from b in Enumerable.Range(1, str.Length)
select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
select string.Join(string.Empty, p);
return results.ToList();
}
public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
{
while (count-- > 0)
{
yield return start++;
}
}
Passing "abc" to above function would returns:
a
b
ab
c
ac
bc
abc
The problem is I actually would like to find out only the "connected" permutations in "original order", for example "abc" should return only
a
b
c
ab
bc
abc
Does anyone have any idea what should I change to achieve above?
By "connected" permutations - you are effectively looking for all substrings from length 1 up to the full length of the string. This can be very easily done with two for loops. The duplicates can be removed by using Linq's Distinct() method.
public List<string> findAllOccurance(string str)
{
List<string> result = new List<string>();
for (int i = 1; i <= str.Length; i++)
{
for (int j=0; j <= str.Length-i; j++)
result.Add(str.Substring(j,i));
}
return result.Distinct().ToList();
}
NOTE - if you really do want to return an empty string - you can either modify the outer loop to start from 0 or simply manually add it after creating the list instance. Modifying the loop will result in str.Length empty strings being added & more work for Distinct() when you know you will only ever always want 1 empty string returned.
List<string> result = new List<string>();
result.Add(String.Empty);
for (int i = 1; i <= str.Length; i++)
.....
I don't know if I understand "connected" right... Maybe you could simply check if a potential result is a part of the original string... Something like this:
public List<string> findAllOccurance(string str)
{
var results = from e in Range(0, BigInteger.Pow(2, str.Length))
let p =
from b in Enumerable.Range(1, str.Length)
select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
let p2 = string.Join(string.Empty, p)
where str.Contains(p2)
select p2;
return results.ToList();
}
public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
{
while (count-- > 0)
{
yield return start++;
}
}
For your code, you are performing bitwise operation in order to find all possible subsets. For the case abc your string length is 3. So possible subsets = 2 ^ 3 = 8. Writing them down and matching the rightmost bit with the leftmost index:
Possible cases:
0 0 0 // gives nothing
0 0 1 // gives 'a' (valid)
0 1 0 // gives 'b' (valid)
0 1 1 // gives 'ab' (valid)
1 0 0 // gives 'c' (valid)
1 0 1 // gives 'ac' (invalid as there is a 0 inbetween and not connected)
1 1 0 // gives 'bc' (valid)
1 1 1 // gives 'abc' (valid)
The above is what I understand for what you count as connected. You can easily perform a check to do this with two loops:
int max_size = BigInteger.Pow(2, str.Length);
int str_size = str.Length;
for(int i = 0; i < max_size; ++i)
{
string ans = "";
for(j = 0; j < str_size; ++j)
{
// We check if the jth bit is set, we print the jth element from the string.
if(i & (1 << j))
ans += str[j];
}
else {
if(ans.Length > 0){
// this means we have already added a character and then the next consecutive bit is '0'
ans = "";
break;
}
}
if(ans != ""){
Console.Writeline(ans); // we print the set. you can control this anyway you want.
}
}
}

Generate range between two strings [AA] -> [CD] or [CCC] -> [DMK]

I want to generate a sequence of strings between two groups that can be either 1 letter [A] -> [F] , 2 letters such as [AA] -> [CD] or any other length like 3 or 4 letters using c#.
For example I can specify the start and end values, and it will generate the sequence.
From [AA] to [CD] should generate
AA
AB
AC
AD
BA
BB
BC
BD
CA
CB
CC
CD
I tried to utilize base-26 algorithm to generate the required sequence but failed to get the required output.
string from ="AA";
string to = "CD";
IEnumerable<string> mysequence = Enumerable.Range(ConvertNumber(from), ConvertNumber(to) - ConvertNumber(from)).Select(ConvertAlpha).ToList();
public static string ConvertAlpha(int value)
{
const int a = (int)'A';
value = value - 1;
var returnValue = new StringBuilder();
while (value > -1)
{
var remainder = value % 26;
returnValue.Insert(0, (char)(a + remainder));
value = value / 26 - 1;
}
return returnValue.ToString();
}
public static int ConvertNumber(string value)
{
const int a = (int)'A' - 1;
int returnValue = 0;
foreach (var character in value.ToUpper())
{
returnValue *= 26;
returnValue += (int)character - a;
}
return returnValue;
}
Using recursion (but with brute-force rather than elegance):
static void Main(string[] args)
{
string fromStr = "AAA";
string toStr = "CDE";
List<string> outputList = new List<string>();
BuildSequence(fromStr, toStr, outputList);
outputList.ForEach(s => { Console.WriteLine(s); });
Console.ReadLine();
}
private static void BuildSequence(
string fromStr,
string toStr,
List<string> outputList,
int index = 0,
string prev = "")
{
IEnumerable<string> newStrList = Enumerable
.Range(fromStr[index], toStr[index] - fromStr[index] + 1)
.Select(c => String.Concat(prev, (char)c));
index += 1;
if (index < fromStr.Length)
{
foreach (string newStr in newStrList)
{
BuildSequence(fromStr, toStr, outputList, index, newStr);
}
}
else
{
outputList.AddRange(newStrList);
}
}
The problem you describe is harder than just converting a base-26 representation to an integer, doing some calculation, and then converting back. Your alpha strings aren't necessarily base-26. For example, you say that given AA and CD, you want to generate
AA, AB, AC, AD
BA, BB, BC, BD
CA, CB, CC, CD
What you really have is a base-4 system that uses the characters A, B, C, and D to represent the numbers 0, 1, 2, and 3. What you're saying here is that you want to generate all the 2-digit, base-4 numbers from 00 through 33.
Given CCC => DMK, it's a base-11 system using digits C through M. It's unclear from your description whether you want:
CCC, CCD, CCE ... CCK
CDC, CDD, CDE ... CDK
...
Or if you want
CCC, CCD, CCE ... CCM
CDC, CDD, CDE ... CDM
...
If you want the former, then each digit position is a different base, and things get even more complicated.
How you define things changes how you would write the code to generate the values.
Regardless or how you want to interpret your alpha values, it's clear that your base-26 conversion functions are incorrect.
Your conversion from int to string has a few errors. In particular, subtracting 1 from the value is going to give you trouble. You can see that if you were to pass 0 to the function. The result would be an empty string.
Here's a correct function:
static string ConvertToBase26(int value)
{
const int a = (int)'A';
var result = new StringBuilder();
do
{
var remainder = value % 26;
value /= 26;
result.Insert(0, (char)(a + remainder);
} while (value > 0);
return result.ToString();
}
Your conversion from base26 to integer has similar errors, due to subtracting 1 from things. Remember, A acts like 0. The corrected function:
static int ConvertFromBase26(string value)
{
const int a = (int)'A';
int result = 0;
foreach (var c in value.ToUpper())
{
result = (result * 26) + (c - a);
}
return result;
}
I recommend renaming your base conversion functions. Your ConvertAlpha function converts an integer to a base-26 string. That's not at all clear in the name, as one could misconstrue "ConvertAlpha" to mean "ConvertFromAlpha". I would recommend ConvertToBase26 and ConvertFromBase26, which are much more explicit and unambiguous.

Split numeric part from alphanumeric string using C#

I have alphanumeric string list.
For example:
1A
2B
7K
10A
I want to get only the numeric part and then compare them, if it is less than 10 I need not to add it in another list.
What I want to know the regex to split the numeric part from the string.
Any help.
What I have done till now is:
if (x == y) // also handles null
return 0;
if (x == null)
return -1;
if (y == null)
return +1;
int ix = 0;
int iy = 0;
while (ix < x.Length && iy < y.Length)
{
if (Char.IsDigit(x[ix]) && Char.IsDigit(y[iy]))
{
// We found numbers, so grab both numbers
int ix1 = ix++;
int iy1 = iy++;
while (ix < x.Length && Char.IsDigit(x[ix]))
ix++;
while (iy < y.Length && Char.IsDigit(y[iy]))
iy++;
string numberFromX = x.Substring(ix1, ix - ix1);
string numberFromY = y.Substring(iy1, iy - iy1);
// Pad them with 0's to have the same length
int maxLength = Math.Max(
numberFromX.Length,
numberFromY.Length);
numberFromX = numberFromX.PadLeft(maxLength, '0');
numberFromY = numberFromY.PadLeft(maxLength, '0');
int comparison = _CultureInfo
.CompareInfo.Compare(numberFromX, numberFromY);
if (comparison != 0)
return comparison;
}
else
{
int comparison = _CultureInfo
.CompareInfo.Compare(x, ix, 1, y, iy, 1);
if (comparison != 0)
return comparison;
ix++;
iy++;
}
}
But I don't want to be so complex in my approach.
So I need a regex to split.
Try IsDigit method of char
var number = int.Parse(new string(someString.Where(char.IsDigit).ToArray()));
if(number<10)
{
someList.Add(number);
}
using All and IsDigit you can take only numeric part of the string, then parse it to int and compare :) There is no need to use Regexes
You can use the code below to split an input string and get the result of number group and alpha group. If one group is not there, the result will be empty string.
string input = "10AAA";
Match m = Regex.Match(input, #"(\d*)(\D*)");
string number = m.Groups[1].Value;
string alpha = m.Groups[2].Value;
you can try it with this one:
string txt="10A";
string re1="(\\d+)"; // Integer Number 1
Regex r = new Regex(re1);
Match m = r.Match(txt);
Are you trying to do this?
int num;
string stringWithNumbers = "10a";
if (int.TryParse(Regex.Replace(stringWithNumbers, #"[^\d]", ""), out num))
{
//The number is stored in the "num" variable, which would be 10 in this case.
if (num >= 10)
{
//Do something
}
}
else
{
//Nothing numeric i the string
}

what is next cell column in Excel - combinations/permutations

I need to know column name of a spread sheet with a given starting colum upto n number of columns
let say starting column is "AB", I want to know the column (label) after 99 columns.
For those who need Ralph answer in T-SQL flavor
Create FUNCTION fsExcelValueToColum(#value int) returns varchar(3) as
begin
DECLARE #DIGIT INT,#RV VARCHAR(3);set #rv=''
IF #VALUE=0 RETURN #rv
WHILE #VALUE > 0
BEGIN
SET #DIGIT = #VALUE % 26
IF #DIGIT = 0
BEGIN
set #RV=#RV+'Z'
set #RV=#RV+dbo.fsExcelValueToColum(#value /26 -1)
return #rv
END
set #rv=#rv+char(#digit+64)
set #value=(#value-#digit) /26
END
return #rv
end
USE [ecs]
GO
/****** Object: UserDefinedFunction [dbo].[fnExcelColumnToValue] Script Date: 12/06/2009 10:33:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[fnExcelColumnToValue](#Column varchar(3)) returns int as
Begin
--declare #column varchar(10); select #column = 'AC'
declare #value int, #pow int,#i int,#n int
select #pow=1,#VALUE=0,#I=LEN(#COLUMN)
SET #I=LEN(#COLUMN)
WHILE #I >= 1
BEGIN
SET #VALUE=#VALUE+#POW*((ASCII(SUBSTRING(UPPER(#COLUMN),#I,1)) - 65) +1)
SET #POW=#POW *26
SET #I=#I-1
END
return #value
end
Think of the characters A, B, ... , Z as representing the values 1, 2, ... 26 (you can't quite think of this as being base-26 because there is no character representing 0 nor can there be as we don't want, for example, AA to mean 0). So we have to engage in some trickery to deal with this:
static int ColumnToValue(string column) {
int value = 0;
int pow = 1;
for (int i = column.Length - 1; i >= 0; i--) {
value += pow * (column[i] - 'A' + 1);
pow *= 26;
}
return value;
}
static string ValueToColumn(int value) {
if (value == 0) {
return string.Empty;
}
StringBuilder sb = new StringBuilder();
while (value > 0) {
int digit = value % 26;
if (digit == 0) {
sb.Insert(0, 'Z');
return sb.Insert(0, ValueToColumn(value / 26 - 1)).ToString();
}
sb.Insert(0,(char)(digit + 'A' - 1));
value = (value - digit) / 26;
}
return sb.ToString();
}
So that
Console.WriteLine(ValueToColumn(ColumnToValue("AB") + 99));
outputs DW and
Console.WriteLine(ValueToColumn(ColumnToValue("AB") - 2));
outputs Z. Obviously you can wrap this all up in a nice class and make it fluent or what have you.
Explanation: Think, for example, of the value 702 and a usual base-26 notation where there is a digit representing 0 (I will use the notation _ to represent this magical digit so that we don't get confused between the value 0 and the digit 0). Let's try to convert 702 (decimal) to base-26. The usual algorithm is compute 702 % 26 which is 0 so that we would have the last digit as being _. Then we would divide by 26 to obtain 27. We would note that 27 % 26 is 1 so that the penultimate digit is A. Then we would divide by 26 to obtain 1, compute 1 % 26 to obtain 1 and report that the most-significant digit is A. We would return AA_ as the string representing 702 in base-26 with digits (_ = 0, A = 1, ... Z = 26) (check: 1 * 26^2 + 1 * 26^1 + 0 * 26 = 702). For our purposes, this is wrong. We wanted to get back the string ZZ (because we have 26 digits A, B, C, ... Z representing 1, 2, ... 26 (remember, no digit representing the value 0!) so that ZZ = 26 * 26^1 + 26 * 26^0 = 702). It turns out in our system that numbers congruent to 0 modulo 26 should have least-significant digit Z. So this suggests that our algorithm should be check and see if value is congruent to 0 modulo 26. If it is, prepend a Z and then prepend the string representing the value value / 26 - 1. This is the algorithm that you see above.
I wrote this a while ago in Clipper (old XBASE compiler)
if nColumn <= 26 // Column 26 or less ?
retval := chr(nColumn+64)
else
temp := int(nColumn/26) // Compute first letter
remd := nColumn % 26 // and second letter and
retval:= if(remd=0,chr(temp+63)+"Z",;
chr(temp+64)+chr(remd+64))
endif
This works for spreadsheets with up to 256 columns, I am not sure if the formula is the same for columns beyond that. I am not sure what programming language you are using, but the Clipper code is pretty simple...
Here's my tuppence worth (quickly written - I'm sure it can be tidied up):-
public static string ToAlpha(int index)
{
if (index <= 0)
{
throw new ArgumentOutOfRangeException("index");
}
--index;
var chars = new List<char>();
int x = index;
do
{
int r = x % 26;
chars.Insert(0, Convert.ToChar(65 + r));
x /= 26;
} while (x > 26);
if (x > 0)
{
chars.Insert(0, Convert.ToChar(64 + x));
}
return new string(chars.ToArray());
}
public static int ToNumeric(string index)
{
int total = 0;
var chars = index.ToCharArray();
int chrIndex = chars.Length - 1;
foreach (char chr in chars)
{
total += (Convert.ToInt32(chr) - 64) * (int)(Math.Pow(26d, (double)chrIndex));
--chrIndex;
}
return total;
}
Usage
string input = "AB";
string output = ToAlpha(ToNumeric(input) + 99);

How to convert a column number (e.g. 127) into an Excel column (e.g. AA)

How do you convert a numerical number to an Excel column name in C# without using automation getting the value directly from Excel.
Excel 2007 has a possible range of 1 to 16384, which is the number of columns that it supports. The resulting values should be in the form of excel column names, e.g. A, AA, AAA etc.
Here's how I do it:
private string GetExcelColumnName(int columnNumber)
{
string columnName = "";
while (columnNumber > 0)
{
int modulo = (columnNumber - 1) % 26;
columnName = Convert.ToChar('A' + modulo) + columnName;
columnNumber = (columnNumber - modulo) / 26;
}
return columnName;
}
If anyone needs to do this in Excel without VBA, here is a way:
=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")
where colNum is the column number
And in VBA:
Function GetColumnName(colNum As Integer) As String
Dim d As Integer
Dim m As Integer
Dim name As String
d = colNum
name = ""
Do While (d > 0)
m = (d - 1) Mod 26
name = Chr(65 + m) + name
d = Int((d - m) / 26)
Loop
GetColumnName = name
End Function
You might need conversion both ways, e.g from Excel column adress like AAZ to integer and from any integer to Excel. The two methods below will do just that. Assumes 1 based indexing, first element in your "arrays" are element number 1.
No limits on size here, so you can use adresses like ERROR and that would be column number 2613824 ...
public static string ColumnAdress(int col)
{
if (col <= 26) {
return Convert.ToChar(col + 64).ToString();
}
int div = col / 26;
int mod = col % 26;
if (mod == 0) {mod = 26;div--;}
return ColumnAdress(div) + ColumnAdress(mod);
}
public static int ColumnNumber(string colAdress)
{
int[] digits = new int[colAdress.Length];
for (int i = 0; i < colAdress.Length; ++i)
{
digits[i] = Convert.ToInt32(colAdress[i]) - 64;
}
int mul=1;int res=0;
for (int pos = digits.Length - 1; pos >= 0; --pos)
{
res += digits[pos] * mul;
mul *= 26;
}
return res;
}
Sorry, this is Python instead of C#, but at least the results are correct:
def ColIdxToXlName(idx):
if idx < 1:
raise ValueError("Index is too small")
result = ""
while True:
if idx > 26:
idx, r = divmod(idx - 1, 26)
result = chr(r + ord('A')) + result
else:
return chr(idx + ord('A') - 1) + result
for i in xrange(1, 1024):
print "%4d : %s" % (i, ColIdxToXlName(i))
I discovered an error in my first post, so I decided to sit down and do the the math. What I found is that the number system used to identify Excel columns is not a base 26 system, as another person posted. Consider the following in base 10. You can also do this with the letters of the alphabet.
Space:.........................S1, S2, S3 : S1, S2, S3
....................................0, 00, 000 :.. A, AA, AAA
....................................1, 01, 001 :.. B, AB, AAB
.................................... …, …, … :.. …, …, …
....................................9, 99, 999 :.. Z, ZZ, ZZZ
Total states in space: 10, 100, 1000 : 26, 676, 17576
Total States:...............1110................18278
Excel numbers columns in the individual alphabetical spaces using base 26. You can see that in general, the state space progression is a, a^2, a^3, … for some base a, and the total number of states is a + a^2 + a^3 + … .
Suppose you want to find the total number of states A in the first N spaces. The formula for doing so is A = (a)(a^N - 1 )/(a-1). This is important because we need to find the space N that corresponds to our index K. If I want to find out where K lies in the number system I need to replace A with K and solve for N. The solution is N = log{base a} (A (a-1)/a +1). If I use the example of a = 10 and K = 192, I know that N = 2.23804… . This tells me that K lies at the beginning of the third space since it is a little greater than two.
The next step is to find exactly how far in the current space we are. To find this, subtract from K the A generated using the floor of N. In this example, the floor of N is two. So, A = (10)(10^2 – 1)/(10-1) = 110, as is expected when you combine the states of the first two spaces. This needs to be subtracted from K because these first 110 states would have already been accounted for in the first two spaces. This leaves us with 82 states. So, in this number system, the representation of 192 in base 10 is 082.
The C# code using a base index of zero is
private string ExcelColumnIndexToName(int Index)
{
string range = string.Empty;
if (Index < 0 ) return range;
int a = 26;
int x = (int)Math.Floor(Math.Log((Index) * (a - 1) / a + 1, a));
Index -= (int)(Math.Pow(a, x) - 1) * a / (a - 1);
for (int i = x+1; Index + i > 0; i--)
{
range = ((char)(65 + Index % a)).ToString() + range;
Index /= a;
}
return range;
}
//Old Post
A zero-based solution in C#.
private string ExcelColumnIndexToName(int Index)
{
string range = "";
if (Index < 0 ) return range;
for(int i=1;Index + i > 0;i=0)
{
range = ((char)(65 + Index % 26)).ToString() + range;
Index /= 26;
}
if (range.Length > 1) range = ((char)((int)range[0] - 1)).ToString() + range.Substring(1);
return range;
}
This answer is in javaScript:
function getCharFromNumber(columnNumber){
var dividend = columnNumber;
var columnName = "";
var modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = String.fromCharCode(65 + modulo).toString() + columnName;
dividend = parseInt((dividend - modulo) / 26);
}
return columnName;
}
Easy with recursion.
public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
int baseValue = Convert.ToInt32('A');
int columnNumberZeroBased = columnNumberOneBased - 1;
string ret = "";
if (columnNumberOneBased > 26)
{
ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
}
return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}
I'm surprised all of the solutions so far contain either iteration or recursion.
Here's my solution that runs in constant time (no loops). This solution works for all possible Excel columns and checks that the input can be turned into an Excel column. Possible columns are in the range [A, XFD] or [1, 16384]. (This is dependent on your version of Excel)
private static string Turn(uint col)
{
if (col < 1 || col > 16384) //Excel columns are one-based (one = 'A')
throw new ArgumentException("col must be >= 1 and <= 16384");
if (col <= 26) //one character
return ((char)(col + 'A' - 1)).ToString();
else if (col <= 702) //two characters
{
char firstChar = (char)((int)((col - 1) / 26) + 'A' - 1);
char secondChar = (char)(col % 26 + 'A' - 1);
if (secondChar == '#') //Excel is one-based, but modulo operations are zero-based
secondChar = 'Z'; //convert one-based to zero-based
return string.Format("{0}{1}", firstChar, secondChar);
}
else //three characters
{
char firstChar = (char)((int)((col - 1) / 702) + 'A' - 1);
char secondChar = (char)((col - 1) / 26 % 26 + 'A' - 1);
char thirdChar = (char)(col % 26 + 'A' - 1);
if (thirdChar == '#') //Excel is one-based, but modulo operations are zero-based
thirdChar = 'Z'; //convert one-based to zero-based
return string.Format("{0}{1}{2}", firstChar, secondChar, thirdChar);
}
}
Same implementation in Java
public String getExcelColumnName (int columnNumber)
{
int dividend = columnNumber;
int i;
String columnName = "";
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
i = 65 + modulo;
columnName = new Character((char)i).toString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
int nCol = 127;
string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol >= 26)
{
int nChar = nCol % 26;
nCol = (nCol - nChar) / 26;
// You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now.
sCol = sChars[nChar] + sCol;
}
sCol = sChars[nCol] + sCol;
Update: Peter's comment is right. That's what I get for writing code in the browser. :-) My solution was not compiling, it was missing the left-most letter and it was building the string in reverse order - all now fixed.
Bugs aside, the algorithm is basically converting a number from base 10 to base 26.
Update 2: Joel Coehoorn is right - the code above will return AB for 27. If it was real base 26 number, AA would be equal to A and the next number after Z would be BA.
int nCol = 127;
string sChars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol > 26)
{
int nChar = nCol % 26;
if (nChar == 0)
nChar = 26;
nCol = (nCol - nChar) / 26;
sCol = sChars[nChar] + sCol;
}
if (nCol != 0)
sCol = sChars[nCol] + sCol;
..And converted to php:
function GetExcelColumnName($columnNumber) {
$columnName = '';
while ($columnNumber > 0) {
$modulo = ($columnNumber - 1) % 26;
$columnName = chr(65 + $modulo) . $columnName;
$columnNumber = (int)(($columnNumber - $modulo) / 26);
}
return $columnName;
}
Just throwing in a simple two-line C# implementation using recursion, because all the answers here seem far more complicated than necessary.
/// <summary>
/// Gets the column letter(s) corresponding to the given column number.
/// </summary>
/// <param name="column">The one-based column index. Must be greater than zero.</param>
/// <returns>The desired column letter, or an empty string if the column number was invalid.</returns>
public static string GetColumnLetter(int column) {
if (column < 1) return String.Empty;
return GetColumnLetter((column - 1) / 26) + (char)('A' + (column - 1) % 26);
}
Although there are already a bunch of valid answers1, none get into the theory behind it.
Excel column names are bijective base-26 representations of their number. This is quite different than an ordinary base 26 (there is no leading zero), and I really recommend reading the Wikipedia entry to grasp the differences. For example, the decimal value 702 (decomposed in 26*26 + 26) is represented in "ordinary" base 26 by 110 (i.e. 1x26^2 + 1x26^1 + 0x26^0) and in bijective base-26 by ZZ (i.e. 26x26^1 + 26x26^0).
Differences aside, bijective numeration is a positional notation, and as such we can perform conversions using an iterative (or recursive) algorithm which on each iteration finds the digit of the next position (similarly to an ordinary base conversion algorithm).
The general formula to get the digit at the last position (the one indexed 0) of the bijective base-k representation of a decimal number m is (f being the ceiling function minus 1):
m - (f(m / k) * k)
The digit at the next position (i.e. the one indexed 1) is found by applying the same formula to the result of f(m / k). We know that for the last digit (i.e. the one with the highest index) f(m / k) is 0.
This forms the basis for an iteration that finds each successive digit in bijective base-k of a decimal number. In pseudo-code it would look like this (digit() maps a decimal integer to its representation in the bijective base -- e.g. digit(1) would return A in bijective base-26):
fun conv(m)
q = f(m / k)
a = m - (q * k)
if (q == 0)
return digit(a)
else
return conv(q) + digit(a);
So we can translate this to C#2 to get a generic3 "conversion to bijective base-k" ToBijective() routine:
class BijectiveNumeration {
private int baseK;
private Func<int, char> getDigit;
public BijectiveNumeration(int baseK, Func<int, char> getDigit) {
this.baseK = baseK;
this.getDigit = getDigit;
}
public string ToBijective(double decimalValue) {
double q = f(decimalValue / baseK);
double a = decimalValue - (q * baseK);
return ((q > 0) ? ToBijective(q) : "") + getDigit((int)a);
}
private static double f(double i) {
return (Math.Ceiling(i) - 1);
}
}
Now for conversion to bijective base-26 (our "Excel column name" use case):
static void Main(string[] args)
{
BijectiveNumeration bijBase26 = new BijectiveNumeration(
26,
(value) => Convert.ToChar('A' + (value - 1))
);
Console.WriteLine(bijBase26.ToBijective(1)); // prints "A"
Console.WriteLine(bijBase26.ToBijective(26)); // prints "Z"
Console.WriteLine(bijBase26.ToBijective(27)); // prints "AA"
Console.WriteLine(bijBase26.ToBijective(702)); // prints "ZZ"
Console.WriteLine(bijBase26.ToBijective(16384)); // prints "XFD"
}
Excel's maximum column index is 16384 / XFD, but this code will convert any positive number.
As an added bonus, we can now easily convert to any bijective base. For example for bijective base-10:
static void Main(string[] args)
{
BijectiveNumeration bijBase10 = new BijectiveNumeration(
10,
(value) => value < 10 ? Convert.ToChar('0'+value) : 'A'
);
Console.WriteLine(bijBase10.ToBijective(1)); // prints "1"
Console.WriteLine(bijBase10.ToBijective(10)); // prints "A"
Console.WriteLine(bijBase10.ToBijective(123)); // prints "123"
Console.WriteLine(bijBase10.ToBijective(20)); // prints "1A"
Console.WriteLine(bijBase10.ToBijective(100)); // prints "9A"
Console.WriteLine(bijBase10.ToBijective(101)); // prints "A1"
Console.WriteLine(bijBase10.ToBijective(2010)); // prints "19AA"
}
1 This generic answer can eventually be reduced to the other, correct, specific answers, but I find it hard to fully grasp the logic of the solutions without the formal theory behind bijective numeration in general. It also proves its correctness nicely. Additionally, several similar questions link back to this one, some being language-agnostic or more generic. That's why I thought the addition of this answer was warranted, and that this question was a good place to put it.
2 C# disclaimer: I implemented an example in C# because this is what is asked here, but I have never learned nor used the language. I have verified it does compile and run, but please adapt it to fit the language best practices / general conventions, if necessary.
3 This example only aims to be correct and understandable ; it could and should be optimized would performance matter (e.g. with tail-recursion -- but that seems to require trampolining in C#), and made safer (e.g. by validating parameters).
I wanted to throw in my static class I use, for interoping between col index and col Label. I use a modified accepted answer for my ColumnLabel Method
public static class Extensions
{
public static string ColumnLabel(this int col)
{
var dividend = col;
var columnLabel = string.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnLabel = Convert.ToChar(65 + modulo).ToString() + columnLabel;
dividend = (int)((dividend - modulo) / 26);
}
return columnLabel;
}
public static int ColumnIndex(this string colLabel)
{
// "AD" (1 * 26^1) + (4 * 26^0) ...
var colIndex = 0;
for(int ind = 0, pow = colLabel.Count()-1; ind < colLabel.Count(); ++ind, --pow)
{
var cVal = Convert.ToInt32(colLabel[ind]) - 64; //col A is index 1
colIndex += cVal * ((int)Math.Pow(26, pow));
}
return colIndex;
}
}
Use this like...
30.ColumnLabel(); // "AD"
"AD".ColumnIndex(); // 30
private String getColumn(int c) {
String s = "";
do {
s = (char)('A' + (c % 26)) + s;
c /= 26;
} while (c-- > 0);
return s;
}
Its not exactly base 26, there is no 0 in the system. If there was, 'Z' would be followed by 'BA' not by 'AA'.
if you just want it for a cell formula without code, here's a formula for it:
IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
In Delphi (Pascal):
function GetExcelColumnName(columnNumber: integer): string;
var
dividend, modulo: integer;
begin
Result := '';
dividend := columnNumber;
while dividend > 0 do begin
modulo := (dividend - 1) mod 26;
Result := Chr(65 + modulo) + Result;
dividend := (dividend - modulo) div 26;
end;
end;
A little late to the game, but here's the code I use (in C#):
private static readonly string _Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static int ColumnNameParse(string value)
{
// assumes value.Length is [1,3]
// assumes value is uppercase
var digits = value.PadLeft(3).Select(x => _Alphabet.IndexOf(x));
return digits.Aggregate(0, (current, index) => (current * 26) + (index + 1));
}
In perl, for an input of 1 (A), 27 (AA), etc.
sub excel_colname {
my ($idx) = #_; # one-based column number
--$idx; # zero-based column index
my $name = "";
while ($idx >= 0) {
$name .= chr(ord("A") + ($idx % 26));
$idx = int($idx / 26) - 1;
}
return scalar reverse $name;
}
Though I am late to the game, Graham's answer is far from being optimal. Particularly, you don't have to use the modulo, call ToString() and apply (int) cast. Considering that in most cases in C# world you would start numbering from 0, here is my revision:
public static string GetColumnName(int index) // zero-based
{
const byte BASE = 'Z' - 'A' + 1;
string name = String.Empty;
do
{
name = Convert.ToChar('A' + index % BASE) + name;
index = index / BASE - 1;
}
while (index >= 0);
return name;
}
More than 30 solutions already, but here's my one-line C# solution...
public string IntToExcelColumn(int i)
{
return ((i<16926? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<2730? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<26? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + ((char)((i%26)+65)));
}
After looking at all the supplied Versions here, I decided to do one myself, using recursion.
Here is my vb.net Version:
Function CL(ByVal x As Integer) As String
If x >= 1 And x <= 26 Then
CL = Chr(x + 64)
Else
CL = CL((x - x Mod 26) / 26) & Chr((x Mod 26) + 1 + 64)
End If
End Function
Refining the original solution (in C#):
public static class ExcelHelper
{
private static Dictionary<UInt16, String> l_DictionaryOfColumns;
public static ExcelHelper() {
l_DictionaryOfColumns = new Dictionary<ushort, string>(256);
}
public static String GetExcelColumnName(UInt16 l_Column)
{
UInt16 l_ColumnCopy = l_Column;
String l_Chars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String l_rVal = "";
UInt16 l_Char;
if (l_DictionaryOfColumns.ContainsKey(l_Column) == true)
{
l_rVal = l_DictionaryOfColumns[l_Column];
}
else
{
while (l_ColumnCopy > 26)
{
l_Char = l_ColumnCopy % 26;
if (l_Char == 0)
l_Char = 26;
l_ColumnCopy = (l_ColumnCopy - l_Char) / 26;
l_rVal = l_Chars[l_Char] + l_rVal;
}
if (l_ColumnCopy != 0)
l_rVal = l_Chars[l_ColumnCopy] + l_rVal;
l_DictionaryOfColumns.ContainsKey(l_Column) = l_rVal;
}
return l_rVal;
}
}
Here is an Actionscript version:
private var columnNumbers:Array = ['A', 'B', 'C', 'D', 'E', 'F' , 'G', 'H', 'I', 'J', 'K' ,'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
private function getExcelColumnName(columnNumber:int) : String{
var dividend:int = columnNumber;
var columnName:String = "";
var modulo:int;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = columnNumbers[modulo] + columnName;
dividend = int((dividend - modulo) / 26);
}
return columnName;
}
JavaScript Solution
/**
* Calculate the column letter abbreviation from a 1 based index
* #param {Number} value
* #returns {string}
*/
getColumnFromIndex = function (value) {
var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
var remainder, result = "";
do {
remainder = value % 26;
result = base[(remainder || 26) - 1] + result;
value = Math.floor(value / 26);
} while (value > 0);
return result;
};
These my codes to convert specific number (index start from 1) to Excel Column.
public static string NumberToExcelColumn(uint number)
{
uint originalNumber = number;
uint numChars = 1;
while (Math.Pow(26, numChars) < number)
{
numChars++;
if (Math.Pow(26, numChars) + 26 >= number)
{
break;
}
}
string toRet = "";
uint lastValue = 0;
do
{
number -= lastValue;
double powerVal = Math.Pow(26, numChars - 1);
byte thisCharIdx = (byte)Math.Truncate((columnNumber - 1) / powerVal);
lastValue = (int)powerVal * thisCharIdx;
if (numChars - 2 >= 0)
{
double powerVal_next = Math.Pow(26, numChars - 2);
byte thisCharIdx_next = (byte)Math.Truncate((columnNumber - lastValue - 1) / powerVal_next);
int lastValue_next = (int)Math.Pow(26, numChars - 2) * thisCharIdx_next;
if (thisCharIdx_next == 0 && lastValue_next == 0 && powerVal_next == 26)
{
thisCharIdx--;
lastValue = (int)powerVal * thisCharIdx;
}
}
toRet += (char)((byte)'A' + thisCharIdx + ((numChars > 1) ? -1 : 0));
numChars--;
} while (numChars > 0);
return toRet;
}
My Unit Test:
[TestMethod]
public void Test()
{
Assert.AreEqual("A", NumberToExcelColumn(1));
Assert.AreEqual("Z", NumberToExcelColumn(26));
Assert.AreEqual("AA", NumberToExcelColumn(27));
Assert.AreEqual("AO", NumberToExcelColumn(41));
Assert.AreEqual("AZ", NumberToExcelColumn(52));
Assert.AreEqual("BA", NumberToExcelColumn(53));
Assert.AreEqual("ZZ", NumberToExcelColumn(702));
Assert.AreEqual("AAA", NumberToExcelColumn(703));
Assert.AreEqual("ABC", NumberToExcelColumn(731));
Assert.AreEqual("ACQ", NumberToExcelColumn(771));
Assert.AreEqual("AYZ", NumberToExcelColumn(1352));
Assert.AreEqual("AZA", NumberToExcelColumn(1353));
Assert.AreEqual("AZB", NumberToExcelColumn(1354));
Assert.AreEqual("BAA", NumberToExcelColumn(1379));
Assert.AreEqual("CNU", NumberToExcelColumn(2413));
Assert.AreEqual("GCM", NumberToExcelColumn(4823));
Assert.AreEqual("MSR", NumberToExcelColumn(9300));
Assert.AreEqual("OMB", NumberToExcelColumn(10480));
Assert.AreEqual("ULV", NumberToExcelColumn(14530));
Assert.AreEqual("XFD", NumberToExcelColumn(16384));
}
Sorry, this is Python instead of C#, but at least the results are correct:
def excel_column_number_to_name(column_number):
output = ""
index = column_number-1
while index >= 0:
character = chr((index%26)+ord('A'))
output = output + character
index = index/26 - 1
return output[::-1]
for i in xrange(1, 1024):
print "%4d : %s" % (i, excel_column_number_to_name(i))
Passed these test cases:
Column Number: 494286 => ABCDZ
Column Number: 27 => AA
Column Number: 52 => AZ
For what it is worth, here is Graham's code in Powershell:
function ConvertTo-ExcelColumnID {
param (
[parameter(Position = 0,
HelpMessage = "A 1-based index to convert to an excel column ID. e.g. 2 => 'B', 29 => 'AC'",
Mandatory = $true)]
[int]$index
);
[string]$result = '';
if ($index -le 0 ) {
return $result;
}
while ($index -gt 0) {
[int]$modulo = ($index - 1) % 26;
$character = [char]($modulo + [int][char]'A');
$result = $character + $result;
[int]$index = ($index - $modulo) / 26;
}
return $result;
}
Another VBA way
Public Function GetColumnName(TargetCell As Range) As String
GetColumnName = Split(CStr(TargetCell.Cells(1, 1).Address), "$")(1)
End Function
Here's my super late implementation in PHP. This one's recursive. I wrote it just before I found this post. I wanted to see if others had solved this problem already...
public function GetColumn($intNumber, $strCol = null) {
if ($intNumber > 0) {
$intRem = ($intNumber - 1) % 26;
$strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
}
return $strCol;
}

Categories