I would like to convert an Excel Range to a C# Array with this code:
System.Array MyRange = (System.Array)range.cells.value;
for (int k = 0; k <= MyRange.Length; k++)
{
List<service_name> _ml = new List<service_name>();
for (int j = 1; j < dataitems.Count; j++)
{
// enter code here
}
}
And then iterate over it like in the above loop.
But this code does not work, and throws this Exception:
"Unable to cast object of type 'System.String' to type 'System.Array'."
Based on the help provided my Microsoft here, this is how I read and write an array in Excel.
var xlApp=new Microsoft.Office.Interop.Excel.Application();
var wb=xlApp.Workbooks.Open(fn, ReadOnly: false);
xlApp.Visible=true;
var ws=wb.Worksheets[1] as Worksheet;
var r=ws.Range["A2"].Resize[100, 1];
var array=r.Value;
// array is object[1..100,1..1]
for(int i=1; i<=100; i++)
{
var text=array[i, 1] as string;
Debug.Print(text);
}
// to create an [1..100,1..1] array use
var array2=Array.CreateInstance(
typeof(object),
new int[] {100, 1},
new int[] {1, 1}) as object[,];
// fill array2
for(int i=1; i<=100; i++)
{
array2[i, 1] = string.Format("Text{0}",i);
}
r.Value2=array2;
wb.Close(SaveChanges: true);
xlApp.Quit();
The error message in the original post occurs when the range consists of exactly one cell, because the resulting value's type is variant, and actually can be array, double, string, date, and null.
One solution can be that you check the cell count and act differently in case of exactly one cell.
My solution creates an array of cells. This works even if one or more cells are empty, which could causes a null object. (When all cells of the range are empty, Range.Cells.Value is null.)
System.Array cellArray = range.Cells.Cast<Excel.Range>().ToArray<Excel.Range>();
If you prefer Lists over Arrays (like I do), you can use this code:
List<Excel.Range> listOfCells = range.Cells.Cast<Excel.Range>().ToList<Excel.Range>();
Range can be one- or two-dimensional.
Finally, if you definitely need a string array, here it is:
string[] strArray = range.Cells.Cast<Excel.Range>().Select(Selector).ToArray<string>();
where Selector function looks like this:
public string Selector(Excel.Range cell)
{
if (cell.Value2 == null)
return "";
if (cell.Value2.GetType().ToString() == "System.Double")
return ((double)cell.Value2).ToString();
else if (cell.Value2.GetType().ToString() == "System.String")
return ((string)cell.Value2);
else if (cell.Value2.GetType().ToString() == "System.Boolean")
return ((bool)cell.Value2).ToString();
else
return "unknown";
}
I included "unknown" for the case I don't remember all data types that Value2 can return. Please improve this function if you find any other type(s).
NOTE: This example only works with a range that is MORE THAN ONE CELL. If the Range is only a single cell (1x1), Excel will treat it in a special way, and the range.Value2 will NOT return a 2-dimensional array, but instead will be a single value. It's these types of special cases that will drive you nuts, as well as zero and non-zero array lower bounds:
using Excel = Microsoft.Office.Interop.Excel;
private static void Test()
{
Excel.Range range = Application.ActiveWorkbook.ActiveSheet.Range["A1:B2"]; // 2x2 array
range.Cells[1, 2] = "Foo"; // Sets Cell A2 to "Foo"
dynamic[,] excelArray = range.Value2 as dynamic[,]; // This is a very fast operation
Console.Out.WriteLine(excelArray[1, 2]); // => Foo
excelArray[1, 2] = "Bar";
range.Value2 = excelArray; // Sets Cell A2 to "Bar", again a fast operation even for large arrays
Console.Out.WriteLine(range.Cells[1, 2]); // => Bar
Note that excelArray will have row and column lower bounds of 1:
Console.Out.WriteLine("RowLB: " + excelArray.GetLowerBound(0)); // => RowLB: 1
Console.Out.WriteLine("ColLB: " + excelArray.GetLowerBound(1)); // => ColLB: 1
BUT, if you declare a newArray in C# and assign it, then the lower bounds will be 0, but it will still work:
dynamic[,] newArray = new dynamic[2, 2]; // Same dimensions as "A1:B2" (2x2)
newArray[0, 1] = "Foobar";
range.Value2 = newArray; // Sets Cell A2 to "Foobar"
Console.Out.WriteLine(range.Cells[1, 2]); // => Foobar
Fetching this value out of the range will give you the original array with lower bounds of 0:
range.Cells[1, 2] = "Fubar";
dynamic[,] lastArray = range.Value2 as dynamic[,];
Console.Out.WriteLine(lastArray[0, 1]); // => Fubar
Console.Out.WriteLine("RowLB: " + lastArray.GetLowerBound(0)); // => RowLB: 0
Console.Out.WriteLine("ColLB: " + lastArray.GetLowerBound(1)); // => ColLB: 0
}
Working with Excel Interop can be daunting as there are many special cases like this in the codebase, but I hope this helps clarify at least this one.
The error means that the value is a string, so you can't convert it directly to array.
If the value is for example comma delimeted string you can use Split to get an array:
string[] MyRange = (range.Cells.Value + "").Split(',');
for (int k = 0; k < MyRange.Length; k++)
{
//...loop here...
}
Also fixed your loop, you were going to get Index Out of Bounds error.
Late to the conversation, but here is a method to do this:
static string[][] GetStringArray(Object rangeValues)
{
string[][] stringArray = null;
Array array = rangeValues as Array;
if (null != array)
{
int rank = array.Rank;
if (rank > 1)
{
int rowCount = array.GetLength(0);
int columnCount = array.GetUpperBound(1);
stringArray = new string[rowCount][];
for (int index = 0; index < rowCount; index++)
{
stringArray[index] = new string[columnCount-1];
for (int index2 = 0; index2 < columnCount; index2++)
{
Object obj = array.GetValue(index + 1, index2 + 1);
if (null != obj)
{
string value = obj.ToString();
stringArray[index][index2] = value;
}
}
}
}
}
return stringArray;
}
called with:
string[][] rows = GetStringArray(range.Cells.Value2);
The issue is because ,when your range becomes a single cell ,and "range.value"/"range.cell.value" means String value,this string cannot be put into object array.
So check if your range has only one cell or more and do according to that
Related
I'm attempting to import a CSV file into a DataTable, however the CSV contains headers that are the same. (For example, there are multiple "Date" headers for different form sections). To fix this, I decided to create a loop that will run through the headers and replace the duplicates or unwanted entries based on their position. I've replaced my replaceWith array with dummy entries, but my actual code does have the correct size to correlate with the replace array.
string[] columnNames = null;
string[] oStreamDataValues = null;
int[] error = {0,1,2,3,4,7,8,9,10,11,15,21,34,37,57,61,65,68,69,71,75,79,82,83,85,89,93,96,97,99,103,107,110,111,113,117,121,124,125,127,128,129,130,132,182,210,212,213,214,215,216,222,226,239};
int[] replace = {14,16,17,17,20,23,24,27,28,29,31,32,44,58,59,60,62,63,64,66,67,70,72,73,74,76,77,78,80,81,84,86,87,88,90,91,92,94,95,98,100,101,102,104,105,106,108,109,112,114,115,116,118,119,120,122,123,126,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,184,186,187,188,190,191,192,194,195,196,198,199,200,202,203,204,206,207,208,209,236,242,243,244};
string[] replaceWith = {"Replace 1", "Replace 2", "Replace 3"};
string fix = "ignore_";
int inc = 00;
string entry = "";
while (!oStreamReader.EndOfStream)
{
string oStreamRowData = oStreamReader.ReadLine().Trim();
if (oStreamRowData.Length > 0)
{
//oStreamDataValues = Regex.Split(oStreamRowData, ",(?=(?:[^']*'[^']*')*[^']*$)");
oStreamDataValues = oStreamRowData.Split(',');
if (rowCount == 0)
{
rowCount = 1;
columnNames = oStreamDataValues;
for (int i = 0; i < columnNames.Length; i++)
{
for (int j = 0; j < error.Length; j++)
{
if (error[j] == i)
{
entry = fix + inc++;
}
}
for (int k = 0; k < replace.Length; k++)
{
if (replace[i] == i)
{
int add = 0;
entry = replaceWith[add++];
}
}
DataColumn oDataColumn = new DataColumn(entry, typeof(string));
oDataColumn.DefaultValue = string.Empty;
oDataTable.Columns.Add(oDataColumn);
}
}
}
I'm no coding expert, so my syntax/decision making isn't perfect.
However the error that I get is that A column named 'ignore_4' already belongs to this DataTable.
I assume something is incorrect in my loop logic.
I think you have overcomplicated the loops. You just need to keep an index of the current position in the array of errors and array of replaces.
string rep = "replace_"; // base string for replace fields
string fix = "ignore_"; // base string for ignore fields
// For demonstation purpose I have commented out this array. If you
// want every 'replace' column have its specific name then prepare this
// array with exactly the number of names required by the number of
// elements in the replace array
//
// string[] replaceWith = {"Replace 1", "Replace 2", "Replace 3"};
int idxErrors = 0; // Current position in the error array
int idxReplace = 0; // Current position in the replace array
int fixCounter = 1;
int repCounter = 1;
string entry = "";
for (int i = 0; i < columnNames.Length; i++)
{
// Is this the index of a column that should be ignored?
if (idxErrors < error.Length && i == error[idxErrors])
{
entry = fix + fixCounter.ToString("D2");
idxErrors++;
fixCounter++;
}
// Is this the index of a column that should have a different name??
else if (idxReplace < replace.Length && i == replace[idxReplace])
{
entry = rep + repCounter.ToString("D2");
// entry = replaceWith[repCounter];
idxReplace++;
repCounter++;
}
else
entry = columnNames[i];
// Now create the column
DataColumn oDataColumn = new DataColumn(entry, typeof(string));
oDataColumn.DefaultValue = string.Empty;
oDataTable.Columns.Add(oDataColumn);
}
In this example I have used the same pattern used for the ignored column also for the columns that need to have the name changed. If you want to give each renamed column a proper name, then you need to prepare an array with these proper names and this array should be of the same length of the replace array. Then use the idxReplace to take the correct name from the array of possible proper names.
I am creating a spreadsheet from a List<object[]> using LoadFromArrays
The first entry of the array is a title, the other entries are possibly numbers, text or dates (but the same for each array in the list).
The generated Excel sheet has the green triangle warning that numbers are formatted as text.
I loop through all the cells and set their format to Number like so ws.Cells[i, j].Style.Numberformat.Format = "0";
However the problem remains and I still see the green warning, even though the number format is set to number when I look in the Format Cell... dialogue.
What are my options here? It is possible for me to know a bit more about what type is in each column, but how do I then set a column title?
Is there a better solution than EPPlus? or some more post processing of the spreadsheet I can do before downloading it?
Since you are using objects arrays they can contain numbers and strings that look like numbers you will have to go through each object and determine its type:
[TestMethod]
public void Object_Type_Write_Test()
{
//http://stackoverflow.com/questions/31537981/using-epplus-how-can-i-generate-a-spreadsheet-where-numbers-are-numbers-not-text
var existingFile = new FileInfo(#"c:\temp\temp.xlsx");
if (existingFile.Exists)
existingFile.Delete();
//Some data
var list = new List<Object[]>
{
new object[]
{
"111.11",
111.11,
DateTime.Now
}
};
using (var package = new ExcelPackage(existingFile))
{
var ws = package.Workbook.Worksheets.Add("Sheet1");
ws.Cells[1, 1, 2, 2].Style.Numberformat.Format = "0";
ws.Cells[1, 3, 2, 3].Style.Numberformat.Format = "[$-F400]h:mm:ss\\ AM/PM";
//This will cause numbers in string to be stored as string in excel regardless of cell format
ws.Cells["A1"].LoadFromArrays(list);
//Have to go through the objects to deal with numbers as strings
for (var i = 0; i < list.Count; i++)
{
for (var j = 0; j < list[i].Count(); j++)
{
if (list[i][j] is string)
ws.Cells[i + 2, j + 1].Value = Double.Parse((string) list[i][j]);
else if (list[i][j] is double)
ws.Cells[i + 2, j + 1].Value = (double)list[i][j];
else
ws.Cells[i + 2, j + 1].Value = list[i][j];
}
}
package.Save();
}
}
With the above, you see the image below as the output Note the upper left corner cell with the green arrow because it was a string that was written by LoadFromArray which looks like a number:
I created an extension method LoadFormulasFromArray, based on EPPlus LoadFromArray. The method assumes all objects in the list are to be treated as formulas (as opposed to LoadFromArray). The big picture is that both Value and Formula properties take string instead of a specific Type. I see this as a mistake because there's no way to differentiate if the string is Text or Formula. Implementing a Formula Type would enable overloading and type checking thus making it possible to always do the right thing.
// usage: ws.Cells[2,2].LoadFormulasFromArrays(MyListOfObjectArrays)
public static class EppPlusExtensions
{
public static ExcelRangeBase LoadFormulasFromArrays(this ExcelRange Cells, IEnumerable<object[]> Data)
{
//thanx to Abdullin for the code contribution
ExcelWorksheet _worksheet = Cells.Worksheet;
int _fromRow = Cells.Start.Row;
int _fromCol = Cells.Start.Column;
if (Data == null) throw new ArgumentNullException("data");
int column = _fromCol, row = _fromRow;
foreach (var rowData in Data)
{
column = _fromCol;
foreach (var cellData in rowData)
{
Cells[row, column].Formula = cellData.ToString();
column += 1;
}
row += 1;
}
return Cells[_fromRow, _fromCol, row - 1, column - 1];
}
}
The trick is to not pass the numbers as "raw objects" to EPPlus but casting them properly.
Here's how I did that in a DataTable-to-Excel export method I made with EPPlus:
if (dc.DataType == typeof(int)) ws.SetValue(row, col, !r.IsNull(dc) ? (int)r[dc] : (int?)null);
else if (dc.DataType == typeof(decimal)) ws.SetValue(row, col, !r.IsNull(dc) ? (decimal)r[dc] : (decimal?)null);
else if (dc.DataType == typeof(double)) ws.SetValue(row, col, !r.IsNull(dc) ? (double)r[dc] : (double?)null);
else if (dc.DataType == typeof(float)) ws.SetValue(row, col, !r.IsNull(dc) ? (float)r[dc] : (float?)null);
else if (dc.DataType == typeof(string)) ws.SetValue(row, col, !r.IsNull(dc) ? (string)r[dc] : null);
else if (dc.DataType == typeof(DateTime))
{
if (!r.IsNull(dc))
{
ws.SetValue(row, col, (DateTime)r[dc]);
// Change the following line if you need a different DateTime format
var dtFormat = "dd/MM/yyyy";
ws.Cells[row, col].Style.Numberformat.Format = dtFormat;
}
else ws.SetValue(row, col, null);
}
IMPORTANT: It's worth noting that DateTime values will require more work to be handled properly, since we would want to have it formatted in a certain way AND, arguably, support NULL values in the column: the above method fullfills both these requirements.
I published the full code sample (DataTable to Excel file with EPPlus) in this post on my blog.
I need someone to create a method that will get me all the cell values in an excel spreadsheet into a 2D array.
I'm making it using ribbons in C# to work with Excel but i just can't get it to work.
private string[,] GetSpreadsheetData ()
{
try
{
Excel.Application exApp =
Globals.TSExcelAddIn.Application as Excel.Application;
Excel.Worksheet ExWorksheet = exApp.ActiveSheet as Excel.Worksheet;
Excel.Range xlRange = ExWorksheet.get_Range("A1","F188000");
object[,] values = (object[,])xlRange.Value2;
string[,] tsReqs = new string[xlRange.Rows.Count, 7];
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
for (int i = 0; i < tsReqs.GetLength(0); i++)
{
for (int z = 0; z < tsReqs.GetLength(1); z++)
{
if(values[i+1,z+1] != null)
tsReqs[i, z] = values[i + 1, z + 1].ToString();
}
}
return tsReqs;
}
catch
{
MessageBox.Show
("Excel has encountered an error. \nSaving work and exitting");
return null;
}
}
Also if anyone has a more efficient way of doing this I would greatly appreciate it.
Excel.Range xlRange = ExWorksheet.get_Range("A1","F188000");
Reads all the way till F188000 cell from A1, I just want it to keep reading until it reaches a row with absolutely no data.
- Caught: "Index was outside the bounds of the array." (System.IndexOutOfRangeException) Exception Message = "Index was outside the bounds of the array.", Exception Type = "System.IndexOutOfRangeException"
You could consider using ExWorksheet.UsedRange instead of ExWorksheet.get_Range("A1","F188000")
EDIT: Also, I think if you use the .Text field of a Range, the value is automatically casted to a string, so no need to use .Value2 here
Excel.Range rng = ExWorksheet.UsedRange;
int rowCount = rng.Rows.Count;
int colCount = rng.Columns.Count;
string[,] tsReqs = new string[rowCount, colCount];
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
string str = rng.Cells[i, j].Text;
tsReqs[i - 1, j - 1] = str;
}
}
Your arrays are different sizes. Your values come from A1:F188000 which is 6 columns, but you're looping through the columns of tsReqs which is 7 columns. It looks like you're trying to account for the fact that values will be a 1-based array but aren't accounting for that properly.
Change the declaration of tsReqs to:
string[,] tsReqs = new string[xlRange.Rows.Count, 6];
and you should be fine.
Try this
private static void printExcelValues(Worksheet xSheet)
{
Range xRng =xSheet.Cells.SpecialCells(
XlCellType.xlCellTypeConstants);
var arr = new string[xRng.Rows.Count,xRng.Columns.Count];
foreach (Range item in xRng)
{
arr[item.Row-1,item.Column-1]=item.Value.ToString();
}
}
You can use the | to specify more cell types like XlCellType.xlCellTypeFormulas or any other type you'd like.
I had to do something very similar. Reading an excel file takes a while... I took a different route but I got the job done with instant results.
Firstly I gave each column its own array. I saved each column from the spreadsheet as a CSV(Comma delimited) file. After opening that file with notePad I was able to copy the 942 values separated with a comma to the initialization of the array
int[] Column1 = {300, 305, 310, ..., 5000};
[0] [1] [2] ... [941]
Now... If you do this for each Column, the position will resemble the 'row' of each 'column' of your 'spreadsheet' .
This odd method worked PERFECT for me, as I needed to compare user input sizes to the values in the "Width" column in the spreadsheet to get information regarding each respective size found in the spreadsheet.
NOTE: If your cells contain strings and not integers like mine, you can use enumeration method:
enum column1 { thing_1, thing_2, ..., thing_n,}
[0] [1] [n]
Here's my code If you want to have a look:
(This is NOT the code converting a spreadsheet into some arrays --that is only a few lines of code, depending on your amount of columns-- this is the whole LookUp method I wrote)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PalisadeWorld
{
//struct to store all the positions of each matched panel size in an array 'Identities'
struct ID
{
public int[] Identities;
public ID(int[] widths, int rows)
{
//Column1 from spreadsheet
int[] allWidths = { 300, 305, 310, 315, 320, 325, 330, ..., 5000 };
int i,j;
int[] Ids = new int[rows];
for (i = 0; i < rows; i++)
{
for (j = 0; j < 941; j++)
{
if (widths[i] == allWidths[j])
{
Ids[i] = j;
break;
}
}
}
this.Identities = Ids;
}
public override string ToString()
{
string data = String.Format("{0}", this.Identities);
return data;
}
}
class LookUpSheet
{
//retrieve user input from another class
public int[] lookUp_Widths {get; set;}
public int lookUp_Rows { get; set; }
//Method returning desired values from Column2
public int[] GetNumPales1()
{
//column2
int[] all_numPales = { 2, 2, 2, 2, 2, 2, 2, 2, 2, ..."goes on till [941]"...};
int[] numPales = new int[lookUp_Rows];
ID select = new ID(lookUp_Widths, lookUp_Rows);
for (int i = 0; i < lookUp_Rows; i++)
{
numPales[i] = all_numPales[select.Identities[i]];
}
return numPales;
}
//Method returning desired values from Column3
public int[] GetBlocks1()
{
//column3
int[] all_blocks = { 56, 59, 61, 64, 66, 69, 71, 74, "goes on till [941]"...};
int[] blocks = new int[lookUp_Rows];
ID select = new ID(lookUp_Widths, lookUp_Rows);
for (int i = 0; i < lookUp_Rows; i++)
{
blocks[i] = all_blocks[select.Identities[i]];
}
return blocks;
}
...
Goes on through each column of my spreadsheet
Really hope this helps someone. Cheers
Im trying to insert RoomType array into the excel book. Range of RoomType is From D22 To D25 so problem is that this code only put the firts value In this range. if i insert RoomType.set_Value into the for loop, excel range filling with last array item. can anyone help me?
Object[,] RoomtypeArray = new object[1, _RoomType.Count];
for (int i = 0; i < _RoomType.Count; i++)
{
RoomtypeArray[0, i] = _RoomType[i];
}
RoomType.set_Value(Type.Missing, RoomtypeArray);
This is what you need:
//Microsoft.Office.Interop.Excel.Range RoomType;
//List<double> _RoomType;
object[,] roomTypeArray = Array.CreateInstance(
typeof(object),
new int[] { 1, _RoomType.Count},
new int[] { 1, 1 });
for (int i = 0; i < _RoomType.Count; i++)
{
roomTypeArray[1, i + 1] = _RoomType[i];
}
RoomType.Value2 = roomTypeArray;
because setting an array for a range requires 1-based indexes instead of 0-based which are used with the new statment in C#.
(look also in the accepted answer of How can I quickly up-cast object[,] into double[,]? to find a neat trick going between object[,] and double[,] for use in Excel Inerop).
i have a string that conatin 5 numbers like
'1,4,14,32,47'
i want to make from this string 5 strings of 4 number in each one
like :
'1,4,14,32'
'1,4,14,47'
'1,4,32,47'
'1,14,32,47'
'4,14,32,47'
what is the simple/faster way to do it
is the way of convert this to array unset every time diffrent entery and combine
them back to string ?
is there a simple way to do it ?
thanks
How about something like
string s = "1,4,14,32,47";
string r = String.Join(",", s.Split(',').Where((x, index) => index != 1).ToArray());
Using string.Split() you can create a string array. Loop through it, so that in each loop iteration you indicate which element should be skipped (on the first pass, ignore the first element, on the second pass, ignore the second element).
Inside that loop, create a new array that contains all elements but the one you want to skip, then use string.Join() to create each result.
Have a look at:
http://msdn.microsoft.com/en-us/magazine/ee310028.aspx Here you'll find an example in F# who will give the correct background in combinations and permutations (that's how is called what you need). There is code too, I think it's easy to translate it in C#
Example of Code in C# (text in Italian but code in English)
For those who need a more generic algorithm, here is one which gives n length subsets of m items:
private void GetPermutations()
{
int permutationLength = 4;
string s = "1,4,14,32,47";
string[] subS = s.Split(',');
int[] indexS = new int[permutationLength];
List<string> result = new List<string>();
IterateNextPerm(permutationLength, indexS, subS, result);
// Result will hold all your genberated data.
}
private void IterateNextPerm(int permutationLength, int[] pIndexes, string[] subS, List<string> result)
{
int maxIndexValue = subS.Count() - 1;
bool isCorrect = true;
for (int index = 0; index < permutationLength - 1; index++)
{
if (pIndexes[index] >= pIndexes[index + 1])
{
isCorrect = false;
break;
}
}
// Print result if correct
if (isCorrect)
{
string strNewPermutation = string.Empty;
for (int index = 0; index < permutationLength; index++)
{
strNewPermutation += subS[pIndexes[index]] + ",";
}
result.Add(strNewPermutation.TrimEnd(','));
}
// Increase last index position
pIndexes[permutationLength - 1]++;
// Check and fix if it's out of bounds
if (pIndexes[permutationLength - 1] > maxIndexValue)
{
int? lastIndexIncreased = null;
// Step backwards and increase indexes
for (int index = permutationLength - 1; index > 0; index--)
{
if (pIndexes[index] > maxIndexValue)
{
pIndexes[index - 1]++;
lastIndexIncreased = index - 1;
}
}
// Normalize indexes array, to prevent unnecessary steps
if (lastIndexIncreased != null)
{
for (int index = (int)lastIndexIncreased + 1; index <= permutationLength - 1; index++)
{
if (pIndexes[index - 1] + 1 <= maxIndexValue)
{
pIndexes[index] = pIndexes[index - 1] + 1;
}
else
{
pIndexes[index] = maxIndexValue;
}
}
}
}
if (pIndexes[0] < maxIndexValue)
{
IterateNextPerm(permutationLength, pIndexes, subS, result);
}
}
I know that it's not the nicest coding, but I've written it right now in the last half an hour so I'm sure there are things to tweek there.
Have fun coding!
var elements = string.Split(',');
var result =
Enumerable.Range(0,elements.Length)
.Reverse()
.Select(
i=>
string.Join(","
Enumerable.Range(0,i).Concat(Enumerable.Range(i+1,elements.Length - i - 1))
.Select(j=>elements[j]).ToArray() // This .ToArray() is not needed in NET 4
)
).ToArray();
your wording is pretty confusing...but the example is clear enough. just split it on commas, then remove one index, then use string.Join(",", list); to put it back together..