C# Loops with Char and Numbers - c#

I have the following line of code in my C# Winforms app:
excell_app.createHeaders(1, 1, "Product_1", "A1", "A1", "n");
Where it says "Product_1" I need it to loop through all my items in my array and where it says "A1", "A1" I need it to get the next value, i.e "B2","B2"
I am unsure as to which loop I should use because I need a for next to interate through my array but then I need to increment the value for the location for "B2","B2"
Here is my attempt:
foreach (string value in ProductName)
{
excell_app.createHeaders(1, 1, "+ value +", "A1", "A1", "n");
}
I do not know how to Iterate through letters and numbers for my location values:
Something like: (I think this may be wrong, please advise)
char X='A'+1;
X++

The column is basically a base 26 number which is using only letters as its symbols. The only odd bit is that there is no symbol for zero.
These methods should do the trick:
private static string ExcelCellReference(int col, int row)
{
return ExcelColumnReference(col) + row;
}
private static string ExcelColumnReference(int col)
{
if (col <= 0)
{
throw new ArgumentOutOfRangeException("col",
"Value must be greater than or equal to 1.");
}
string columnString = "";
do
{
col--;
int remainder;
// Math.DivRem divides by 26 and also gets the remainder.
col = Math.DivRem(col, 26, out remainder);
columnString = (char)('A' + remainder) + columnString;
} while (col > 0);
return columnString;
}
ExcelCellReference(1, 1) will return A1, ExcelCellReference(28, 2) will return AB2, etc.

private String getColumnHeader(int column)
{
column--;
if (column >= 0 && column < 26)
{
return (Char)('A' + column) + "";
}
else
{
return getColumnHeader(column / 26) + getColumnHeader(column % 26 + 1);
}
}
private int getColumnIndex(String reference)
{
int retVal = 0;
retVal += reference.Substring(reference.Length - 1)[0] - 'A';
if (reference.Length > 1)
{
reference = reference.Substring(0, reference.Length - 1);
retVal += 26 * getColumnIndex(reference);
}
return retVal + 1;
}

Related

How do I find all possible combinations of the form ±1 ± 2 ± 3 ± ... ± n = k with LINQ?

I am having a very difficult time to come up with a simple solution using LINQ in C# for this problem:
For two given numbers n and k, find all possible combinations of the form ±1 ± 2 ± 3 ± ... ± n = k.
For example, for n = 5 and k = 3, the result would be
"-1+2+3+4-5 = 3", "-1+2+3+4-5 = 3"
public static void Main()
{
int firstNNumbers = Convert.ToInt32(Console.ReadLine());
int numberOfOperations = firstNNumbers - 1;
int targetSum = Convert.ToInt32(Console.ReadLine());
char[] set = { '+', '-' };
bool hasSolution = false;
GetAllOperatorCombinations(set, numberOfOperations, targetSum, ref hasSolution);
if (hasSolution)
{
return;
}
Console.WriteLine("N/A");
}
public static int CheckIfGoodAndPrint(string prefix, int targetSum, ref bool hasSolution)
{
const int Number = 2;
int thisSum = 1;
if (prefix == null)
{
return -1;
}
for (int i = 0; i < prefix.Length; i++)
{
if (prefix[i] == '-')
{
thisSum -= i + Number;
}
else
{
thisSum += i + Number;
}
}
if (thisSum != targetSum)
{
return -1;
}
PrinEquation(prefix, targetSum);
hasSolution = true;
return 1;
}
static void GetAllOperatorCombinations(char[] set, int k, int targetSum, ref bool hasSolution)
{
int n = set.Length;
GetAllOperatorCombinations(set, "", n, k, targetSum, ref hasSolution);
}
static void GetAllOperatorCombinations(char[] set, string prefix, int n, int k, int targetSum, ref bool hasSolution)
{
if (k == 0)
{
int test = CheckIfGoodAndPrint(prefix, targetSum, ref hasSolution);
return;
}
for (int i = 0; i < n; ++i)
{
string newPrefix = prefix + set[i];
GetAllOperatorCombinations(set, newPrefix, n, k - 1, targetSum, ref hasSolution);
}
}
private static void PrinEquation(string prefix, int targetSum)
{
string equation = "";
for (int i = 1; i <= prefix.Length; i++)
{
equation += i + " " + prefix[i - 1] + " ";
if (i == prefix.Length)
{
equation += (i + 1) + " = " + targetSum;
}
}
Console.WriteLine(equation);
}
This is the code that works for all cases but I know it can be done a lot shorter with linq.
Here's a possible iterative solution:
using System;
using System.Linq;
public class Program
{
public static void Main()
{
const int N = 5, K = 3;
// 1 represents +, 0 represents -
var results = Enumerable.Range(0, 1 << N)
.Select(bits =>
{
var permutation = Enumerable.Range(0, N)
.Select(n => (bits & (1 << n)) != 0 ? (n + 1) : -(n + 1))
.ToList();
var sum = permutation.Sum();
var str = string.Join(" + ", permutation);
return new {sum, str};
})
.Where(intermediate => intermediate.sum == K)
.Select(intermediate => $"{intermediate.str} = {K}");
Console.WriteLine(string.Join("\n", results));
}
}
This makes use of the fact that one can iterate through the binary representation of all integers from 0 to 2^N - 1, in order to generate all possible permutations of either + or - (in this case, represented by bits 1 and 0 respectively.)
This essentially turns this problem into a single loop.
Why this works is pretty intuitive; to put it very simply, there are 2^N possible N-length sequences of a two-valued type, and there are also 2^N integers between 0 and 2^N - 1 (obviously), so each possibility must be encountered exactly once.
For your inputs N = 5 and K = 3, this produces (ideone)
-1 + 2 + 3 + 4 + -5 = 3
1 + -2 + 3 + -4 + 5 = 3
-1 + -2 + -3 + 4 + 5 = 3
public static IEnumerable<string> CombinationOfSigns(this int n,int k)
{
IEnumerable<string> signs = new string[] {""};
return Enumerable.Range(0, n)
.Aggregate(signs,(e,y) => e
.SelectMany(x => new string[] { x + "-", x + "+" }))
.Where(combination => Enumerable.Range(0, n)
.Aggregate(0, (sum, number)=> combination[number] == '+' ? sum + (number + 1) : sum - (number + 1)) == k);
}
This what I came up with in the end.

Extracting values from string input

I am trying an efficient way to split up a string. I have a string in the below format which represents a value.
string input = "1A2B3C4D5DC";
i have to fetch the numeric value next to each character , so that i can compute the final value.
Currently im doing this, This works fine, Can you suggest me a better approach.
public double GetValue(string input)
{
string value;
int beginIndex = 0, endIndex = 0, unit1 = 0, unit2 = 0, unit3 = 0, unit4 = 0, unit5 = 0;
input = input.Replace("cd", "zz");
if (input.ToLower().Contains("a"))
{
endIndex = input.ToLower().IndexOf('a');
value = input.Substring(beginIndex, endIndex - beginIndex);
int.TryParse(value, out unit1);
beginIndex = endIndex + 1;
}
if (input.ToLower().Contains("b"))
{
endIndex = input.ToLower().IndexOf('b');
value = input.Substring(beginIndex, endIndex - beginIndex);
int.TryParse(value, out unit2);
beginIndex = endIndex + 1;
}
if (input.ToLower().Contains("c") )
{
endIndex = input.ToLower().IndexOf('b');
value = input.Substring(beginIndex, endIndex - beginIndex);
int.TryParse(value, out unit3);
beginIndex = endIndex + 1;
}
if (input.ToLower().Contains("d"))
{
endIndex = input.ToLower().IndexOf('d');
value = input.Substring(beginIndex, endIndex - beginIndex);
int.TryParse(value, out unit4);
beginIndex = endIndex + 1;
}
if (input.Length > beginIndex + 2)
{
value = input.Substring(beginIndex, input.Length - beginIndex - 2);
int.TryParse(value, out unit5);
}
return (unit1 * 10 + unit2 * 20 + unit3 * 30 + unit4 * 40 + unit5 * 50); //some calculation
}
Possible inputs can be : 21A34DC , 4C, 2BDC, 2B. basically they all are optional but if present it has to be in the same sequence
you can find all numbers within string with a regular expression:
string input = "1A2B3C4D5DC";
Regex rx = new Regex(#"\d+");
// Regex rx = new Regex(#"-?\d+"); // this one includes negative integers
var matches = rx.Matches(input);
int[] numbers = matches.OfType<Match>()
.Select(m => Convert.ToInt32(m.Value))
.ToArray();
make necessary computations with resulting array.
If you want to extract just numbers from string, then use Regular Expressions:
string input = "1A2B3C4D5DC";
var resultString = Regex.Replace(input, #"[^0-9]+", "");
Or linq way:
string input = "1A2B3C4D5DC";
var resultString = new String(input.Where(Char.IsDigit).ToArray());
Just looking at your code there is a lot of repeating code, so refactoring it "as is" and using a mapping dictionary is likely good solurtion
Something like this
public static double GetValue(string input)
{
var map = new Dictionary<string, int>()
{
{"a", 10 }, {"b", 20}, {"c", 30}, {"d", 40}
};
int result = 0;
foreach(var i in map)
{
int endIndex, outValue;
string value;
endIndex = input.ToLower().IndexOf(i.Key);
value = input.Substring(endIndex -1, 1);
int.TryParse(value, out outValue);
result += (i.Value * outValue);
}
return result;
}
Following code for me ,
public double GetValue(string input)
{
input)= input)();
string value;
int aValue = 0, bValue = 0, cValue = 0, dvalue = 0, cdValue = 0;
if (match.Groups[5].Success && !string.IsNullOrEmpty(match.Groups[5].Value))
{
string val = match.Groups[5].Value;
if (!int.TryParse(val.Substring(0, val.Length - 2), out cdValue))
{
return -1;
}
}
if (match.Groups[4].Success && !string.IsNullOrEmpty(match.Groups[4].Value))
{
string val = match.Groups[4].Value;
if (!int.TryParse(val.Substring(0, val.Length - 1), out dvalue))
{
return -1;
}
}
if (match.Groups[3].Success && !string.IsNullOrEmpty(match.Groups[3].Value))
{
string val = match.Groups[3].Value;
if (!int.TryParse(val.Substring(0, val.Length - 1), out cValue))
{
return -1;
}
}
if (match.Groups[2].Success && !string.IsNullOrEmpty(match.Groups[2].Value))
{
string val = match.Groups[2].Value;
if (!int.TryParse(val.Substring(0, val.Length - 1), out bValue))
{
return -1;
}
}
if (match.Groups[1].Success && !string.IsNullOrEmpty(match.Groups[1].Value))
{
string val = match.Groups[1].Value;
if (!int.TryParse(val.Substring(0, val.Length - 1), out aValue))
{
return -1;
}
}
return (aValue * 10 + bValue * 20 + cValue * 30 + dvalue * 40 + cdValue * 50); //some calculation
}
Tell me if this produces the expected output:
static void Main(string[] args)
{
int sum = GetValue("1A2B3C4D5DC");
// {1,2,3,4,5} = 10*(1+2*2+3*3+4*4+5*5) = 550
}
public static int GetValue(string input)
{
// make input all lowercase
input = input.ToLower();
// replace terminator dc with next letter to
// avoid failing the search;
input = input.Replace("dc", "e");
// initialize all unit values to zero
const string tokens = "abcde";
int[] units = new int[tokens.Length];
// keep track of position of last parsed number
int start = 0;
for (int index = 0; index < tokens.Length; index++)
{
// fetch next letter
char token = tokens[index];
// find letter in input
int position = input.IndexOf(token, start);
// if found
if (position>start)
{
// extract string before letter
string temp = input.Substring(start, position-start);
// and convert to integer
int.TryParse(temp, out units[index]);
}
// update last parsed number
start = position+1;
}
// add unit values, each one worth +10 more than the
// previous one.
//
// {x,y,z} = 10*x + 20*y + 30*z
int sum = 0;
for (int i = 0; i < units.Length; i++)
{
sum += 10*(i+1)*units[i];
}
return sum;
}
}
Please add some test cases in the question with the expected results just to make sure our answers are correct.
"1A2B3C4D5DC" => 550
???

Generate (pseudo-) base-26 number representation (similar to Excel column names) [duplicate]

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
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))
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;
}
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;
}

How to improve efficiency - string representation of an integer using standard incremental routine

I created a thread for this but then deleted it as I wasnt making myself clear.
This routine (my code) gives me the string representation of currentCombination.
using System;
using System.Collections.Generic;
namespace SlowGen
{
class MyClass
{
private List<char> _data = new List<char>();
private List<char> _c;
public MyClass(List<char> chars, Int64 currentCombination)
{
_c = chars;
_data.Add(_c[0]);
for (int i = 0; i < currentCombination - 1; i++)
{
if (i < currentCombination - _c.Count)
IncrementFast();
else
Increment();
}
}
public void Increment()
{
Increment(0);
}
public void Increment(int charIndex)
{
if (charIndex + 1 > _data.Count)
_data.Add(_c[0]);
else
{
if (_data[charIndex] != _c[_c.Count - 1])
{
_data[charIndex] = _c[_c.IndexOf(_data[charIndex]) + 1];
}
else
{
_data[charIndex] = _c[0];
Increment(charIndex + 1);
}
}
}
public void IncrementFast()
{
IncrementFast(0);
}
public void IncrementFast(int charIndex)
{
if (charIndex + 1 > _data.Count)
_data.Add(_c[0]);
else
{
if (_data[charIndex] != _c[_c.Count - 1])
{
_data[charIndex] = _c[_c.Count-1];
}
else
{
_data[charIndex] = _c[0];
Increment(charIndex + 1);
}
}
}
public string Value
{
get
{
string output = string.Empty;
foreach (char c in _data)
output = c + output;
return output;
}
}
}
}
Using this example would create A,B,C,AA,AB,AC,BA etc..
List<char> a = new List<char>();
a.Add('A');
a.Add('B');
a.Add('C');
MyClass b = new MyClass(a,3);
//b.Value: C
MyClass c = new MyClass(a,4);
//c.Value: AA
Now I have this code, which is much more efficient, but the patter differs
static void Main(string[] args)
{
char[] r = new char[] { 'A', 'B', 'C' };
for (int i = 0; i <= 120; i++)
{
string xx = IntToString(i, r);
Console.WriteLine(xx);
System.Threading.Thread.Sleep(100);
}
Console.ReadKey();
}
public static string IntToString(int value, char[] baseChars)
{
string result = string.Empty;
int targetBase = baseChars.Length;
do
{
result = baseChars[value % targetBase] + result;
value = value / targetBase;
}
while (value > 0);
return result;
}
It outputs A,B,C,BA,BB,
I need the sequence of the first section of code with the elegance of the second, can anyone advise?
Thankyou
You need the behaviour to change for columns besides the units column, as you've no doubt noticed. Since the values for non-units column you see are 1 too high, you need to compensate by subtracting 1 first. Or at least that's what seemed to work here:
public static string IntToString(int value, char[] baseChars)
{
string result = string.Empty;
int targetBase = baseChars.Length;
do
{
int currentValue = value % targetBase;
result = baseChars[currentValue] + result;
value = value - currentValue; //possibly not necessary due to integer division rounding down anyway
value = value / targetBase;
value = value - 1;
}
while (value > -1);
return result;
}
Here are some worked examples:
6 with targetBase 2 is AAA:
6%2 is 0, place A on right, half to 3, subtract 1 to 2
2%2 is 0, place A, half to 1, subtract 1 to 0
0%2 is 0, place A, we're done
5 with targetBase 2 is BB:
5%2 is 1, place B on right, subtract 1, half to 2, subtract 1 to 1
1%2 is 1, place B, subtract 1, we're done
7 with target base 3 is BB:
7%3 is 1, place B on right, subtract 1 to 6, 1/3 to 2, subtract 1 to 1
1%3 is 1, place B on right, subtract 1, we're done

Fastest function to generate Excel column letters in C#

What is the fastest c# function that takes and int and returns a string containing a letter or letters for use in an Excel function? For example, 1 returns "A", 26 returns "Z", 27 returns "AA", etc.
This is called tens of thousands of times and is taking 25% of the time needed to generate a large spreadsheet with many formulas.
public string Letter(int intCol) {
int intFirstLetter = ((intCol) / 676) + 64;
int intSecondLetter = ((intCol % 676) / 26) + 64;
int intThirdLetter = (intCol % 26) + 65;
char FirstLetter = (intFirstLetter > 64) ? (char)intFirstLetter : ' ';
char SecondLetter = (intSecondLetter > 64) ? (char)intSecondLetter : ' ';
char ThirdLetter = (char)intThirdLetter;
return string.Concat(FirstLetter, SecondLetter, ThirdLetter).Trim();
}
I currently use this, with Excel 2007
public static string ExcelColumnFromNumber(int column)
{
string columnString = "";
decimal columnNumber = column;
while (columnNumber > 0)
{
decimal currentLetterNumber = (columnNumber - 1) % 26;
char currentLetter = (char)(currentLetterNumber + 65);
columnString = currentLetter + columnString;
columnNumber = (columnNumber - (currentLetterNumber + 1)) / 26;
}
return columnString;
}
and
public static int NumberFromExcelColumn(string column)
{
int retVal = 0;
string col = column.ToUpper();
for (int iChar = col.Length - 1; iChar >= 0; iChar--)
{
char colPiece = col[iChar];
int colNum = colPiece - 64;
retVal = retVal + colNum * (int)Math.Pow(26, col.Length - (iChar + 1));
}
return retVal;
}
As mentioned in other posts, the results can be cached.
I can tell you that the fastest function will not be the prettiest function. Here it is:
private string[] map = new string[]
{
"A", "B", "C", "D", "E" .............
};
public string getColumn(int number)
{
return map[number];
}
Don't convert it at all. Excel can work in R1C1 notation just as well as in A1 notation.
So (apologies for using VBA rather than C#):
Application.Worksheets("Sheet1").Range("B1").Font.Bold = True
can just as easily be written as:
Application.Worksheets("Sheet1").Cells(1, 2).Font.Bold = True
The Range property takes A1 notation whereas the Cells property takes (row number, column number).
To select multiple cells: Range(Cells(1, 1), Cells(4, 6)) (NB would need some kind of object qualifier if not using the active worksheet) rather than Range("A1:F4")
The Columns property can take either a letter (e.g. F) or a number (e.g. 6)
Here's my version: This does not have any limitation as such 2-letter or 3-letter.
Simply pass-in the required number (starting with 0) Will return the Excel Column Header like Alphabet sequence for passed-in number:
private string GenerateSequence(int num)
{
string str = "";
char achar;
int mod;
while (true)
{
mod = (num % 26) + 65;
num = (int)(num / 26);
achar = (char)mod;
str = achar + str;
if (num > 0) num--;
else if (num == 0) break;
}
return str;
}
I did not tested this for performance, if someone can do that will great for others.
(Sorry for being lazy) :)
Cheers!
You could pre-generate all the values into an array of strings. This would take very little memory and could be calculated on the first call.
Here is a concise implementation using LINQ.
static IEnumerable<string> GetExcelStrings()
{
string[] alphabet = { string.Empty, "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" };
return from c1 in alphabet
from c2 in alphabet
from c3 in alphabet.Skip(1) // c3 is never empty
where c1 == string.Empty || c2 != string.Empty // only allow c2 to be empty if c1 is also empty
select c1 + c2 + c3;
}
This generates A to Z, then AA to ZZ, then AAA to ZZZ.
On my PC, calling GetExcelStrings().ToArray() takes about 30 ms. Thereafter, you can refer to this array of strings if you need it thousands of times.
Once your function has run, let it cache the results into a dictionary. So that, it won't have to do the calculation again.
e.g. Convert(27) will check if 27 is mapped/stored in dictionary. If not, do the calculation and store "AA" against 27 in the dictionary.
The absolute FASTEST, would be capitalizing that the Excel spreadsheet only a fixed number of columns, so you would do a lookup table. Declare a constant string array of 256 entries, and prepopulate it with the strings from "A" to "IV". Then you simply do a straight index lookup.
Try this function.
// Returns name of column for specified 0-based index.
public static string GetColumnName(int index)
{
var name = new char[3]; // Assumes 3-letter column name max.
int rem = index;
int div = 17576; // 26 ^ 3
for (int i = 2; i >= 0; i++)
{
name[i] = alphabet[rem / div];
rem %= div;
div /= 26;
}
if (index >= 676)
return new string(name, 3);
else if (index >= 26)
return new string(name, 2);
else
return new string(name, 1);
}
Now it shouldn't take up that much memory to pre-generate each column name for every index and store them in a single huge array, so you shouldn't need to look up the name for any column twice.
If I can think of any further optimisations, I'll add them later, but I believe this function should be pretty quick, and I doubt you even need this sort of speed if you do the pre-generation.
Your first problem is that you are declaring 6 variables in the method. If a methd is going to be called thousands of times, just moving those to class scope instead of function scope will probably cut your processing time by more than half right off the bat.
This is written in Java, but it's basically the same thing.
Here's code to compute the label for the column, in upper-case, with a 0-based index:
public static String findColChars(long index) {
char[] ret = new char[64];
for (int i = 0; i < ret.length; ++i) {
int digit = ret.length - i - 1;
long test = index - powerDown(i + 1);
if (test < 0)
break;
ret[digit] = toChar(test / (long)(Math.pow(26, i)));
}
return new String(ret);
}
private static char toChar(long num) {
return (char)((num % 26) + 65);
}
Here's code to compute 0-based index for the column from the upper-case label:
public static long findColIndex(String col) {
long index = 0;
char[] chars = col.toCharArray();
for (int i = 0; i < chars.length; ++i) {
int cur = chars.length - i - 1;
index += (chars[cur] - 65) * Math.pow(26, i);
}
return index + powerDown(chars.length);
}
private static long powerDown(int limit) {
long acc = 0;
while (limit > 1)
acc += Math.pow(26, limit-- - 1);
return acc;
}
#Neil N -- nice code I think the thirdLetter should have a +64 rather than +65 ? am I right?
public string Letter(int intCol) {
int intFirstLetter = ((intCol) / 676) + 64;
int intSecondLetter = ((intCol % 676) / 26) + 64;
int intThirdLetter = (intCol % 26) + 65; ' SHOULD BE + 64?
char FirstLetter = (intFirstLetter > 64) ? (char)intFirstLetter : ' ';
char SecondLetter = (intSecondLetter > 64) ? (char)intSecondLetter : ' ';
char ThirdLetter = (char)intThirdLetter;
return string.Concat(FirstLetter, SecondLetter, ThirdLetter).Trim();
}
Why don't we try factorial?
public static string GetColumnName(int index)
{
const string letters = "ZABCDEFGHIJKLMNOPQRSTUVWXY";
int NextPos = (index / 26);
int LastPos = (index % 26);
if (LastPos == 0) NextPos--;
if (index > 26)
return GetColumnName(NextPos) + letters[LastPos];
else
return letters[LastPos] + "";
}
Caching really does cut the runtime of 10,000,000 random calls to 1/3 its value though:
static Dictionary<int, string> LetterDict = new Dictionary<int, string>(676);
public static string LetterWithCaching(int index)
{
int intCol = index - 1;
if (LetterDict.ContainsKey(intCol)) return LetterDict[intCol];
int intFirstLetter = ((intCol) / 676) + 64;
int intSecondLetter = ((intCol % 676) / 26) + 64;
int intThirdLetter = (intCol % 26) + 65;
char FirstLetter = (intFirstLetter > 64) ? (char)intFirstLetter : ' ';
char SecondLetter = (intSecondLetter > 64) ? (char)intSecondLetter : ' ';
char ThirdLetter = (char)intThirdLetter;
String s = string.Concat(FirstLetter, SecondLetter, ThirdLetter).Trim();
LetterDict.Add(intCol, s);
return s;
}
I think caching in the worst-case (hit every value) couldn't take up more than 250kb (17576 possible values * (sizeof(int)=4 + sizeof(char)*3 + string overhead=2)
It is recursive. Fast, and right :
class ToolSheet
{
//Not the prettyest but surely the fastest :
static string[] ColName = new string[676];
public ToolSheet()
{
ColName[0] = "A";
for (int index = 1; index < 676; ++index) Recurse(index, index);
}
private int Recurse(int i, int index)
{
if (i < 1) return 0;
ColName[index] = ((char)(65 + i % 26)).ToString() + ColName[index];
return Recurse(i / 26, index);
}
public string GetColName(int i)
{
return ColName[i - 1];
}
}
sorry there was a shift. corrected.
class ToolSheet
{
//Not the prettyest but surely the fastest :
static string[] ColName = new string[676];
public ToolSheet()
{
for (int index = 0; index < 676; ++index)
{
Recurse(index, index);
}
}
private int Recurse(int i, int index)
{
if (i < 1)
{
if (index % 26 == 0 && index > 0) ColName[index] = ColName[index - 1].Substring(0, ColName[index - 1].Length - 1) + "Z";
return 0;
}
ColName[index] = ((char)(64 + i % 26)).ToString() + ColName[index];
return Recurse(i / 26, index);
}
public string GetColName(int i)
{
return ColName[i - 1];
}
}
My solution:
static class ExcelHeaderHelper
{
public static string[] GetHeaderLetters(uint max)
{
var result = new List<string>();
int i = 0;
var columnPrefix = new Queue<string>();
string prefix = null;
int prevRoundNo = 0;
uint maxPrefix = max / 26;
while (i < max)
{
int roundNo = i / 26;
if (prevRoundNo < roundNo)
{
prefix = columnPrefix.Dequeue();
prevRoundNo = roundNo;
}
string item = prefix + ((char)(65 + (i % 26))).ToString(CultureInfo.InvariantCulture);
if (i <= maxPrefix)
{
columnPrefix.Enqueue(item);
}
result.Add(item);
i++;
}
return result.ToArray();
}
}
barrowc's idea is much more convenient and fastest than any conversion function! i have converted his ideas to actual c# code that i use:
var start = m_xlApp.Cells[nRow1_P, nCol1_P];
var end = m_xlApp.Cells[nRow2_P, nCol2_P];
// cast as Range to prevent binding errors
m_arrRange = m_xlApp.get_Range(start as Range, end as Range);
object[] values = (object[])m_arrRange.Value2;
private String columnLetter(int column) {
if (column <= 0)
return "";
if (column <= 26){
return (char) (column + 64) + "";
}
if (column%26 == 0){
return columnLetter((column/26)-1) + columnLetter(26) ;
}
return columnLetter(column/26) + columnLetter(column%26) ;
}
Just use an Excel formula instead of a user-defined function (UDF) or other program, per Allen Wyatt (https://excel.tips.net/T003254_Alphabetic_Column_Designation.html):
=SUBSTITUTE(ADDRESS(ROW(),COLUMN(),4),ROW(),"")
(In my organization, using UDFs would be very painful.)
The code I'm providing is NOT C# (instead is python) but the logic can be used for any language.
Most of previous answers are correct. Here is one more way of converting column number to excel columns.
solution is rather simple if we think about this as a base conversion. Simply, convert the column number to base 26 since there is 26 letters only.
Here is how you can do this:
steps:
set the column as a quotient
subtract one from quotient variable (from previous step) because we need to end up on ascii table with 97 being a.
divide by 26 and get the remainder.
add +97 to remainder and convert to char (since 97 is "a" in ASCII table)
quotient becomes the new quotient/ 26 (since we might go over 26 column)
continue to do this until quotient is greater than 0 and then return the result
here is the code that does this :)
def convert_num_to_column(column_num):
result = ""
quotient = column_num
remainder = 0
while (quotient >0):
quotient = quotient -1
remainder = quotient%26
result = chr(int(remainder)+97)+result
quotient = int(quotient/26)
return result
print("--",convert_num_to_column(1).upper())
If you need to generate letters not starting only from A1
private static string GenerateCellReference(int n, int startIndex = 65)
{
string name = "";
n += startIndex - 65;
while (n > 0)
{
n--;
name = (char)((n % 26) + 65) + name;
n /= 26;
}
return name + 1;
}

Categories

Resources