I want to test a binary search in console app. I've populalated my array. I have no errors. Code runs... I'm not sure what lines of code I need to test this.
Here is my code..
internal class Program
{
static void Main(string[] args)
{
//Initialise array
int[] arr = { 800, 11, 50, 771, 649, 770, 240, 9 };
int key = 0;
Program.BinarySearchDisplay(arr, key);
}
//Binary Search Method
public static object BinarySearchDisplay(int[] arr, int key)
{
int minNum = 0;
int maxNum = arr.Length - 1;
while (minNum <= maxNum)
{
int mid = (minNum + maxNum) / 2;
if (key == arr[mid])
{
return ++mid;
}
else if (key < arr[mid])
{
maxNum = mid - 1;
}
else
{
minNum = mid + 1;
}
}
return "None";
}
}
}
A couple of things of note here. Although technically correct, it is not a good idea to return values of different types from a function. C# being statically typed provides the opportunity to expect certain return types that are used to check the code doesn't contain errors at compile type.
A function needs to return a value, and so you need to assign this value to a variable. This is an example of how to do this for a function called Fun()
int x = Fun(a,b,c);
Here is one way to achieve what you are trying to do. Have a function that returns a value if successful or flag when it does not succeed. Return a bool type indicating success, and include an out parameter that gets assigned a value before the function exits.
Notice that you store the results of the function in a variable found of type bool and then act accordingly using an if(found) statement
class Program
{
static void Main(string[] args)
{
//Initialise array
int[] arr = { 800, 11, 50, 771, 649, 770, 240, 9 };
int key = 50;
Console.WriteLine($"Array: {string.Join(",", arr)}");
Console.WriteLine($"Key: {key}");
// call the function an store the results in a variable
bool found = BinarySearchDisplay(arr, key, out int index);
if (found)
{
Console.WriteLine($"Found arr[{index}] = {arr[index]}");
}
else
{
Console.WriteLine("Not Found.");
}
}
/// <summary>
/// Binary Search Method.
/// </summary>
/// <param name="arr">The array of values.</param>
/// <param name="key">The key to search for.</param>
/// <param name="index">The array index if key was found, -1 otherwise.</param>
/// <returns>true if key found, false otherwise.</returns>
public static bool BinarySearchDisplay(int[] arr, int key, out int index)
{
int minIndex = 0;
int maxIndex = arr.Length - 1;
index = -1;
while (minIndex <= maxIndex)
{
index = (minIndex + maxIndex) / 2;
if (key == arr[index])
{
return true;
}
else if (key < arr[index])
{
maxIndex = index - 1;
}
else
{
minIndex = index + 1;
}
}
return false;
}
}
Note that Program.BinarySearchDisplay() is replaced by just BinarySearchDisplay(). This is because the function is within the same class Program and there is no need to fully qualify its name.
The result of the above code is
Array: 800,11,50,771,649,770,240,9
Key: 50
Found arr[2] = 50
I think there was an error in the op code in return ++mid; as the next index value is returned. Maybe this was done because indexing is 0-based, and the op wanted a 1-based result. But mixing the two styles is dangerous and will lead to bugs.
This is a similar pattern to bool int.TryParse(string, out int) to convert a string to a number if possible, or return false otherwise.
if(int.TryParse("1150", out int x))
{
// x holds the value 1150
}
Related
I have a problem with code.
I receive an error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'GenericMethods.search(T[], T)'. There is no implicit reference conversion from 'object' to 'System.IComparable'.
Task:
Create a console app and write a generic method, Search [ int Search( T [ ] dataArray, T searchKey) ]
that searches an array using linear search algorithm.
a) Method Search should compare the search key with each element in the array until the search key
is found or until the end of the array is reached.
b) If the search key is found, return/display its location in the array (i.e. its index value); otherwise
return -1.
c) You need to populate the array with random values. ( int values – between 10 and 49, double
values between 50 and 99, char values between a and z). The size of array as 10.
d) Test this method by passing two types of arrays to it. (an integer array and a string array) Display
the generated values so that the user knows what values he/she can search for.
[Hint: use (T: IComparable) in the where clause for method Search so that you can use method CompareTo() to
compare the search key to the elements in the array]
My code:
using System;
using System.Collections.Generic;
namespace LinearSearch
{
class GenericMethods
{
static void Main(string[] args)
{
object[] dataArray = new object[10];
Random random = new Random();
for (int i = 0; i < dataArray.Length; i++)
{
int randomType = random.Next(1, 3);
if (randomType == 1)
{
char randomChar = (char)random.Next('a', 'z');
dataArray[i] = randomChar;
}
else if (randomType == 2)
{
double randomDouble = random.Next(50, 99);
dataArray[i] = (int)randomDouble;
}
else
{
int randomInt = random.Next(10, 49);
dataArray[i] = randomInt;
}
}
Console.WriteLine("Generated array is: ");
Console.WriteLine(string.Join(" ", dataArray));
Console.WriteLine("Please, enter number from 10 to 99 or char from A to Z");
object userInput = Console.ReadLine();
Console.WriteLine(userInput);
Console.WriteLine($"Location of search value {userInput}: {search(dataArray, userInput)}");
}//end Main method
private static int search<T>(T[] dataArray, T searchKey) where T : IComparable<T>
{
// default to -1 so that we can determine the search is successful when it becomes a positive value
int arrayPosition = -1;
for (int x = 0; x < dataArray.Length; x++)
{
T arrayElement = dataArray[x];
// Console.WriteLine($"CompareTo result: {searchValue.CompareTo(arrayElement)}");
if (searchKey.CompareTo(arrayElement) == 0)
{
// value is found
arrayPosition = x;
break;
}
}
return arrayPosition;
} // end searchValue
}
}
Could you please help me to fix this problem? I am new in C#..
Instead of declaring dataArray as an object[] declare it as an IComparable[]. You wrote the type constraint limiting your generic type T to IComparable. object does not implement IComparable, so it is not a valid type
Lucky me, I always write generic searches for my code. For other search methods with Generics in C#, you can find them here.
public static int LinearSearch<T>(T[] array, T item) // O(n)
{
for (int i = 0; i < array.Length; i++)
/* array[i] == item */
if (Comparer<T>.Default.Compare(array[i], item) == 0)
return i;
return -1; // Not found
}
You must import 'System.Collections.Generic' in your file.
using System.Collections.Generic;
I found solution
string[] resultArray = Array.ConvertAll(dataArray, x => x.ToString());
After that code works
I am trying to get al the combinations that at least reaches 100. If you add one to another so 10+10+10+10+10+10+10+10+10+10(100)>= 100, but also 20+20+20+20+10+15(105)>=100. But right now it only shows a few because I don't know how i can let him show every possible combination.
I use a for loop in a while so it'll add till the 'GETALTEBEREIKEN' is exceded. but than it'll just check after all is added. And even if it is added i dont get ever 10*10. Because it'll just go to the next number in the array. So it doesn't give me all combinations.
static void Main(string[] args)
{
const int TOTAALGETALLEN = 3;
const int GETALTEBEREIEKEN = 100;
int[] Getallen = new int[TOTAALGETALLEN];
Getallen[0] = 10;
Getallen[1] = 15;
Getallen[2] = 20;
int totaal = 0;
string GebruikteGetallen;
for(int i = 0; i < TOTAALGETALLEN; i++)
{
totaal = Getallen[i];
GebruikteGetallen = i + ", ";
while (totaal<GETALTEBEREIEKEN)
{
for(int j = 0; j < TOTAALGETALLEN; j++)
{
totaal += Getallen[j];
GebruikteGetallen += j + ", ";
}
}
Console.WriteLine(GebruikteGetallen);
Console.WriteLine(totaal);
}
Console.ReadLine();
}
it should subsets (combinations of elements of a set) that fulfill a criterion.
I also found this:
static void Main(string[] args)
{
int[] set = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach (string s in GetCombinations(set, 18, ""))
{
Console.WriteLine(s);
}
Console.ReadLine();
}
public static IEnumerable<string> GetCombinations(int[] set, int sum, string values)
{
for (int i = 0; i < set.Length; i++)
{
int left = sum - set[i];
string vals = set[i] + "," + values;
if (left == 0)
{
yield return vals;
}
else
{
int[] possible = set.Take(i).Where(n => n <= sum).ToArray();
if (possible.Length > 0)
{
foreach (string s in GetCombinations(possible, left, vals))
{
yield return s;
}
}
}
}
}
But this wont let me use the same Number once again. Maybe it will help with your answer.
Alright I have written a program to solve this.
Since you want to be variable I have used recursion instead of stacked loops.
I also added many comments to make it easier to understand how it works.
If you have the correct solution please check if the result is fine.
internal class Program {
public static void Main(string[] args) {
// these are the same numbers, but you can replace or add some
const int limit = 100;
// if you don't know what a dictionary does you should google that
var resources = new Dictionary<Good, int>();
// this is the price of the resource
resources[Good.Copper] = 20;
resources[Good.Tin] = 15;
resources[Good.Iron] = 10;
//resources[Good.Paper] = 8;
//resources[Good.Plastic] = 6;
//resources[Good.Water] = 2;
// Now we want to calculate all possible combinations.
// We can not just put some loops into each other because when we have 4 instead of 3 resources we would need 4 loops.
// Instead we will use some concept called recursion.
// First we sort the resources from expensive to cheap
var sortedResources = resources.OrderByDescending(x => x.Value);
// all combinations will be stored in here
var allSolutions = new List<List<KeyValuePair<Good, int>>>();
// We will start with the maximum amount of the most expensive good and then lower its amount and check all amount of the other goods.
var calculator = new CombinationCalculator(limit, sortedResources.ToList(), allSolutions);
calculator.CalculateCombinationsRecursive(0, 0, new List<KeyValuePair<Good, int>>());
Console.WriteLine("\nAll solutions calculated, " + allSolutions.Count + " combinations found.");
Console.ReadKey();
}
}
This are the different resources
internal enum Good {
Copper = 1,
Tin = 2,
Iron = 3,
Paper = 4,
Plastic = 5,
Water = 6
}
This class is calculating the combinations.
internal class CombinationCalculator {
private readonly List<List<KeyValuePair<Good, int>>> _allSolutions;
private readonly int _limit;
private readonly List<KeyValuePair<Good, int>> _sortedResources;
/// <summary>
/// This class will calculate all combinations
/// </summary>
/// <param name="limit">The minimum cost (100 for example)</param>
/// <param name="sortedResources">All resources and their individual price sorted descending.</param>
/// <param name="allSolutions">all completed combinations of resources and each amount.</param>
public CombinationCalculator(int limit, List<KeyValuePair<Good, int>> sortedResources, List<List<KeyValuePair<Good, int>>> allSolutions) {
_limit = limit;
_sortedResources = sortedResources;
_allSolutions = allSolutions;
}
/// <summary>
/// Find all combinations recursive.
/// </summary>
/// <param name="index">The resource that should be added next.</param>
/// <param name="currentPrice">The price what the resources that are already added cost.</param>
/// <param name="resources">All resources that are already added and their amount.</param>
internal void CalculateCombinationsRecursive(int index, int currentPrice, List<KeyValuePair<Good, int>> resources) {
// we calculate the amount af this resource needed to get atleast the limit
var maximumAmount = (int)Math.Ceiling((_limit - currentPrice) / (1.0 * _sortedResources[index].Value));
// with maximum amount you have one combination already
var firstCombi = resources.ToList();
firstCombi.Add(new KeyValuePair<Good, int>(_sortedResources[index].Key, maximumAmount));
Console.WriteLine("Found one combination: ");
foreach(var res in firstCombi) {
Console.Write(" " + res.Key + " * " + res.Value + ",");
}
Console.WriteLine(" price: " + (currentPrice + maximumAmount * _sortedResources[index].Value));
_allSolutions.Add(firstCombi);
// if this is already the last resource we can't add more
if(index == _sortedResources.Count - 1) {
return;
}
// now find all other possible combinations recursive
for(var i = maximumAmount - 1; i >= 0; i--) {
// since we add less than maximum amount we will need to fill the price with the other resources
var newResources = resources.ToList();
newResources.Add(new KeyValuePair<Good, int>(_sortedResources[index].Key, i));
// this method calls itself recursive
CalculateCombinationsRecursive(index + 1, currentPrice + i * _sortedResources[index].Value, newResources);
}
}
}
If you have questions feel free to ask.
I hope this is useful for you, if you want to test other stuff just modify the first part of the main method and the enum.
Hi guys im trying to learn permutation and recurtion. And im looking for a way how can i use bought at the same time.
MAIN:
namespace Recursive_Permutation
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[5] { 0, 0, 0, 0, 0 };
CalPermutations CP = new CalPermutations();
CP.Run(array, array.Length-1);
}
}
}
Here is my Simple code:
namespace Recursive_Permutation
{
public class CalPermutations
{
public int Run(int[] array,int indexer)
{
if (indexer > array.Length)
{
return 1;
}
else
{
for (int i = 0; i <= array.Length; i++)
{
array[indexer] = i;
Display(array);
}
Run(array, indexer-1);
}
return indexer;
}
public void Display(int[] array)
{
foreach (int num in array)
{
Console.Write(num);
}
Console.WriteLine();
}
}
}
And here is the Output of the program:
Question:
it might be simple to other but im kind of confuse now in how can i manipulate it that it still count the first digit (position [0]) 1 to 5 and go next position and (position 1) and add 1 and go back to [0] and start count again till it reaches 5.
i hope that my explanation is understandable.. thx.
I put together this simpler example of using recursion and permutation. It uses strings internally, but produces the same result.
Its for proof of concept only, since nobody will us recursion for this simple stuff in a professional environment. Recursion can have a big memory impact, but makes describing some problems in a simple way possible.
If I had to choose between iterative and recursive solutions, I would take the iterative one most of the time.
// Main entrance
public void DoStuff()
{
// define variations
List<string> possibilities = new List<string>() { "0", "1", "2", "3", "4", "5" };
// resultlist, will be filled later
List<string> permutations = new List<string>();
// how many values will be taken from the possibilities
int digits = 5;
//do the work
Permute(permutations, possibilities, digits, "");
// display the work
foreach (var item in permutations)
{
Console.WriteLine(item);
}
}
/// <summary>
/// generates a List of permuted strings
/// </summary>
/// <param name="permutations">resultlist</param>
/// <param name="possibilities">possible values of the digit</param>
/// <param name="digitsLeft">how many digits shall be appended</param>
/// <param name="current">the current value of the unfinished result</param>
private void Permute(List<string> permutations, List<string> possibilities, int digitsLeft, string current)
{
// uncomment to see how it works in detail
//Console.WriteLine("step:"+current);
// most important: define Stop conditions for the recursion
// safety stop
if (digitsLeft < 0)
{// end of digits :), normally we never end up here
return;
}
// normal stop
if (digitsLeft == 0)
{// normal endpoint, add the found permutation to the resultlist
permutations.Add(current);
return;
}
// now prepare the recursion, try each possibility
foreach (var item in possibilities)
{
// digitsLeft need to be decreased, since we add a concrete digit to the current value (current+item)
// important: (current + item) generates a new string in memory, the old values won't be touched, permutations possibilities are references, so no memory impact here
Permute(permutations, possibilities, digitsLeft - 1, current + item);
}
}
Update: added comments on each method as per comment.
public class Program
{
public static void Main(string[] args)
{
int[] array = new int[] { 0, 0, 0, 0, 0};
CalPermutations CP = new CalPermutations();
CP.Run(array, 0);
}
}
public class CalPermutations
{
// Prints all the permutations of array, starting at the specified index.
public void Run(int[] array, int indexer)
{
if (indexer < 0 || indexer >= array.Length)
return;
// Keep [0, indexer] combination constant, change combination on right i.e. (indexer, Array.length).
Run(array, indexer+1);
// All the elements on right have finished, increment current element.
array[indexer]++;
// Check if current combination is STILL valid.
if(array[indexer] <= array.Length)
{
// since current combination is still valid, display it, and execute the process again on the new combination.
Display(array);
Run(array, indexer);
}
else
{
// Since current element is out of range, reset it.
array[indexer] = 1;
}
}
// Prints all the elements in array.
public void Display(int[] array)
{
foreach (int num in array)
Console.Write(num);
Console.WriteLine();
}
}
Situation:
I'm new to c# and currently learning the ropes whilst also polishing up on my data structures, I decided to make a class that'd perform multiple functions to a linear array, since It was suggested to me that I should start with linear arrays then work on a circular one.
The methods my class currently provides are:
adding an item to the front-most position of the array,
adding an item to the back-most position of the array,
removing the first item in the array,
removing the last item in the array, //todo
clearing the current array list of it's values,
displaying the array list contents to the user.
Problem:
I'm having difficulty constructing a method that removes the last item of the array, I've looked online and the pre-writen methods seem complex and I can't get my head around them due to my in-experience. I realize it must be easy for others to write a method like this, but I'm truly stumped.
I'd like to learn how to write a method that removes the last value in the array, in the most simpliest to understand way. Here is my current code for my LinearArrayList class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace arraydatastructuresactual
{
public class LinearArrayList
{
private int count; //how many numbers currently stored
private int[] values; //array to hold values entered into list
//constructors
/// <summary>
/// //creates a linear array that can hold max values
/// </summary>
/// <param name="max"></param>
public LinearArrayList(int max)
{
count = 0;
values = new int[max]; //makes the linear array as big as the max value
}
/// <summary>
/// //default constructor sets capacity to 10
/// </summary>
public LinearArrayList()
{
count = 0;
values = new int[10];
}
/// <summary>
/// returns true if list is empty
/// otherwise turns false
/// </summary>
/// <returns>true if empty otherwise false</returns>
public bool isEmpty()
{
return (count == 0);
}
/// <summary>
/// returns true if list is full
/// otherwise turns false
/// </summary>
/// <returns>true if full otherwise false</returns>
public bool isFull()
{
return (values.Length <= count);
}
/// <summary>
/// if not full adds value to the end of list
/// throws exception if list is fulll
/// </summary>
/// <param name="value">value to add to end of list</param>
public void addLast(int value) //adds an item to the last position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
values[count++] = value;
}
}
public void addFirst(int value) //Adds an item to the first position in the array.
{
if (isFull())
{
throw new Exception("List Full");
}
else
{
for (int i = count; i > 0; i--)
{
values[i] = values[i--];
}
values[0] = value;
count++;
}
}
public int removeFirst() //removes the first item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = 0; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public int removeLast() //todo //removes the last item from the array
{
if (isEmpty())
throw new Exception("List is Empty");
int value = values[0];
count--;
for (int i = count; i < count; i++)
{
values[i] = values[i + 1];
}
return value;
}
public void displayUI()//displays contents of list
{
}
public void destroy() //Empties The List
{
}
}
}
If someone could share their experience on how I'd go about achieving this, then many thanks, I tried to repurpose my removeFirst method but I messed up, tried to do this a few times and I'm completely stumped now.
You just need to write
public int removeLast()
{
if (isEmpty())
throw new Exception("List is Empty");
count--;
return values[count];
}
this will return the last item in the values array WITHOUT changing its size but decrementing the variable that keeps track of the item actually inserted in the array.
Notice that I don't try to change the value in the location pointed by the count variable. It is still there until you overwrite it adding another value
So you could still write this
// Creates an array with space for 10 ints
LinearArrayList la = new LinearArrayList();
la.addLast(34);
la.addLast(23);
la.addLast(56);
la.addLast(467);
la.addLast(43);
la.addLast(666);
la.addLast(7989);
la.addLast(82);
la.addLast(569);
la.addLast(100);
int value = la.removeLast();
// This will work because you still have a slot free in the 10 ints array
la.addLast(1110);
// While this will fail because the array has now all slots filled
la.addLast(9435);
An alternative to Sybren's answer:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
Array.Copy(values, newValues, newValues.Length);
values = newValues;
return lastValue;
or
int lastValue = values[values.Length - 1];
Array.Resize(values, values.Length - 1);
return lastValue;
If you don't want to use any existing methods of Array class, you can also:
int lastValue = values[values.Length - 1];
int[] newValues = new int[values.Length - 1];
for (int i = 0; i < newValues.Length; i++)
{
newValues[i] = values[i];
}
values = newValues;
return lastValue;
Edit
Forget this, do what #Steve said.
Here's a way to do it. You're converting your array to a list, getting the last element from the list, removing the last element from the list, and convert it back to an array.
var numbersList = values.ToList();
var last = numbersList.Last();
numbersList.Remove(last);
values = numbersList.ToArray();
return last;
This question already has answers here:
What is the algorithm to convert an Excel Column Letter into its Number?
(11 answers)
Closed 9 years ago.
I was wondering what is the best way to convert excel sheet column names into numbers.
I'm working with Excel Package, a good library to handle .xlsx documents. This library unfortunately doesn't have this functionality included.
OBS: The first column, A, corresponds
to number 1 in this library.
This function should work for an arbitrary length column name.
public static int GetColumnNumber(string name)
{
int number = 0;
int pow = 1;
for (int i = name.Length - 1; i >= 0; i--)
{
number += (name[i] - 'A' + 1) * pow;
pow *= 26;
}
return number;
}
I had to deal with this a few months ago. The inverse - column index to column name - is fun, too, and becomes really messy if you try to solve it with a zero based index not recognizing that this complicates things. It could be so simple if it would be a normal polyadic numeral system ...
Here is a simplified version of my solution as a extension method without error handling and all that stuff.
public static Int32 ToOneBasedIndex(this String name)
{
return name.ToUpper().
Aggregate(0, (column, letter) => 26 * column + letter - 'A' + 1);
}
I've been working with this for a while now and found this to work really good for columns that go beyond A-Z, or even beyond AA-ZZ... It's accomplished by breaking apart each character in the string and recursively calling itself to derive the DEC value of the ASCII character (less 64), then multiplying it by 26^n. A return value of long was used to overcome a potential limitation when n > 4.
public long columnNumber(String columnName)
{
char[] chars = columnName.ToUpper().ToCharArray();
return (long)(Math.Pow(26, chars.Count() - 1)) *
(System.Convert.ToInt32(chars[0]) - 64) +
((chars.Count() > 2) ? columnNumber(columnName.Substring(1, columnName.Length - 1)) :
((chars.Count() == 2) ? (System.Convert.ToInt32(chars[chars.Count() - 1]) - 64) : 0));
}
Also, if you'd like to get the inverse (i.e. pass in the columnNumber and get the columnName, here's some code that works for that.
public String columnName(long columnNumber)
{
StringBuilder retVal = new StringBuilder();
int x = 0;
for (int n = (int)(Math.Log(25*(columnNumber + 1))/Math.Log(26)) - 1; n >= 0; n--)
{
x = (int)((Math.Pow(26,(n + 1)) - 1) / 25 - 1);
if (columnNumber > x)
retVal.Append(System.Convert.ToChar((int)(((columnNumber - x - 1) / Math.Pow(26, n)) % 26 + 65)));
}
return retVal.ToString();
}
Source code:
namespace XLS
{
/// <summary>
/// Represents a single cell in a excell sheet
/// </summary>
public struct Cell
{
private long row;
private long column;
private string columnAddress;
private string address;
private bool dataChange;
/// <summary>
/// Initializes a new instance of the XLS.Cell
/// class with the specified row and column of excel worksheet
/// </summary>
/// <param name="row">The row index of a cell</param>
/// <param name="column">The column index of a cell</param>
public Cell(long row, long column)
{
this.row = row;
this.column = column;
dataChange = true;
address = string.Empty;
columnAddress = string.Empty;
}
/// <summary>
/// Initializes a new instance of the XLS.Cell
/// class with the specified address of excel worksheet
/// </summary>
/// <param name="address">The adress of a cell</param>
public Cell(string address)
{
this.address = address;
dataChange = false;
row = GetRow(address);
columnAddress = GetColumnAddress(address);
column = GetColumn(columnAddress);
}
/// <summary>
/// Gets or sets the row of this XLS.Cell
/// </summary>
public long Row
{
get { return row <= 0 ? 1 : row; }
set { row = value; dataChange = true; }
}
/// <summary>
/// Gets or sets the column of this XLS.Cell
/// </summary>
public long Column
{
get { return column <= 0 ? 1 : column; }
set { column = value; dataChange = true; }
}
/// <summary>
/// Gets or sets the address of this XLS.Cell
/// </summary>
public string Address
{
get { return dataChange ? ToAddress() : address; }
set
{
address = value;
row = GetRow(address);
column = GetColumn(address);
}
}
/// <summary>
/// Gets the column address of this XLS.Cell
/// </summary>
public string ColumnAddress
{
get { return GetColumnAddress(Address); }
private set { columnAddress = value; }
}
#region Private Methods
private static long GetRow(string address)
{
return long.Parse(address.Substring(GetStartIndex(address)));
}
private static string GetColumnAddress(string address)
{
return address.Substring(0, GetStartIndex(address)).ToUpperInvariant();
}
private static long GetColumn(string columnAddress)
{
char[] characters = columnAddress.ToCharArray();
int sum = 0;
for (int i = 0; i < characters.Length; i++)
{
sum *= 26;
sum += (characters[i] - 'A' + 1);
}
return (long)sum;
}
private static int GetStartIndex(string address)
{
return address.IndexOfAny("123456789".ToCharArray());
}
private string ToAddress()
{
string indexToString = string.Empty;
if (Column > 26)
{
indexToString = ((char)(65 + (int)((Column - 1) / 26) - 1)).ToString();
}
indexToString += (char)(65 + ((Column - 1) % 26));
dataChange = false;
return indexToString + Row;
}
#endregion
}
}
O24 has a column number and you want a name:
=LEFT(RIGHT(ADDRESS(1,O24),LEN(ADDRESS(1,O24))-1),FIND("$",RIGHT((ADDRESS(1,O24)),LEN(ADDRESS(1,O24))-1))-1)
O37 has a column name and you want a number:
=COLUMN(INDIRECT(O37&1))
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] + "";
}