Been a while since i have programmed, so forgive the rustiness.
I'm trying to populate a multidimensional string array, from an Excel sheet.
The array looks like this
string[,] calendarArray = new string[,]
{
{RowValue1,ColumnValue1},
{RowValue2,ColumnValue1},
etc
};
I want to pull in RowValue and ColumnValue from from the Excel sheet. Pulling the data from Excel isn't the hurdle, can someone please let me know the most efficient way of getting the data into the string array?
You can read Range.Value directly as an array. This gets an Object[,], so not exactly the String[,] you requested, but see if this works for you:
dynamic obj = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
dynamic wb = obj.Workbooks(1);
Object[,] x = wb.Worksheets(1).Range("A1:C2").Value;
Console.WriteLine($"{x.GetLength(0)} x {x.GetLength(1)} items");
Console.WriteLine($"A2 = {x[2,1]}");
Related
Coming from Python, I could easily do array[0][0], but doesn't seem like it in C#.
When I try to fetch data from my MySQL database, it gives me a 2D array, hence the need to use a 2D array.
Array looks like this:
[[hello], [world]]
I'd like to just fetch the string "hello". How would I manage that?
You use
string value = array[0,0];
Here:
var array= new String[,] {{"Hello","World"}};
string value=array[0,0];
You can access multidimensional arrays like this:
int val = a[2,3];
The above statement takes 4th element from the 3rd row of the array.
In your case it would be:
string val = a[0,0];
Pretty straightforward: arrray[0, 0]
Reference
It has been a few years since i have messed with C# or programming for that matter. I am attempting to read a CSV file to multiple integers. The CSV file is formatted as follows
box1,3
box2,6
box3,10
...
box160,1
So far for my code i have the below. The TextFieldParser i got off of another question. I am not sure if that is even what i need. I do not need to keep the information before the "," on the CSV file i just need the information after the "," to correspond with the correct int in my code. Any help or pointers would be much appreciated.
int box1;
int box2;
int box3;
...
int box160;
using (TextFieldParser parser = new TextFieldParser(#"C:\SprinklerTimer\DailySprinklerTimer.csv"))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
//TODO: Process field
}
}
}
For starters manually making 160 box integers is very inefficient. Try using an array.
int[] box; // declare numbers as an int array of any size
box = new int[160]; //New box array for 0-159
and you can either do the same for the value, I.e. a value[] array or what I would is make box a struct instead of int, where the struct has two integers.
struct SimpleStruct
{
int name, value;
}
SimpleStruct[] box; // declare numbers as an int array of any size
box = new SimpleStruct[160]; //New box array for 0-159
And to go on to your actual question, I would recommend this question which will help if you implement my above changes.
Read CSV files to two arrays c#
I saw this link - C# Transpose() method to transpose rows and columns in excel sheet in stackoverflow and this is what I am trying to do. But the guy is pretty unhelpful in the answers as he does not provide the full information needed. I am simply wanting to transpose cells A9:B15 in my excel sheet and then copy them either into a new xls file, a new worksheet, or better yet delete the current worksheet contents and replace it with the newly transposed paste contents. Clearly it can be done through the WorksheetFunction.Transpose method but I can't seem to get it to work as I don't know what rng or value2 are? I could create a datatable but surly using this method seems a more appropriate way of doing it. Here is the code from the stackoverflow question. .
Object[,] transposedRange = (Object[,])xlApp.WorksheetFunction.Transpose(rng.Value2);
xlApp.ActiveSheet.Range("A1").Resize(transposedRange.GetUpperBound(0), transposedRange.GetUpperBound(1)) = transposedRange;
Here is my code so far:
Application excel = new Application();
Workbook wb = excel.Workbooks.Open(#"P:\Visual Studio 2013\Projects\Debugging\Debugging\test.htm");
Microsoft.Office.Interop.Excel.Range rng = excel.get_Range("A9:B15");
Object[,] transposeRange = (Object[,])excel.WorksheetFunction.Transpose(rng);
transposeRange = excel.ActiveSheet.Range("A1").Resize(transposeRange.GetUpperBound(0), transposeRange.GetUpperBound(1));
wb.SaveAs(#"P:\Visual Studio 2013\Projects\Debugging\Debugging\testing.xls");
Not sure if I have done the rng right. I am so confused by this.
Is there some reason you need to do this in C#?
If what you want is just what you state, VBA code can accomplish this also. Just
read the transposed range into a variant array
clear the worksheet
write the variant array back to the worksheet at the cell of your choice.
Note that when you write the variant array back to the worksheet, the destination range must be the same size as the array.
Option Explicit
Sub TransposeRange()
Dim RGtoTranspose As Range
Dim V As Variant
Set RGtoTranspose = Range("A9:B15")
V = WorksheetFunction.Transpose(RGtoTranspose)
Cells.Clear
Range("a1").Resize(UBound(V, 1), UBound(V, 2)).Value = V
End Sub
Seems like nobody actually bothered to answer this and its still the top search engine hit for this issue (# July 2019, go figure...!), so here's my 2 cents...
I did not understand the hype about the WorksheetFunction.Transpose method. "Objectifying" things around isn't perhaps the cleanest way to go about this, particularly when using the Excel Interop anyway. At the end of the day, Transpose has been a dynamic parameter of the PasteSpecial() method since time immemorial. So why not use it as such? I think this was what prompted some people to suggest using VBA instead of C#... Anyway, this code works and does what the question requires methinks:
First get the references right...
using System;
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;
Then try this...
string filePath = #"P:\Visual Studio 2013\Projects\Debugging\Debugging\test.htm";
string savePath = #"P:\Visual Studio 2013\Projects\Debugging\Debugging\testing.xls";
var excelApp = new Excel.Application()
{
Visible = true //This is optional
};
Workbooks workbook = excelApp.Workbooks;
workbook.Open(filePath);
Range range = excelApp.get_Range("A9:B15");
range.Copy();
excelApp.ActiveSheet.Range("A1").PasteSpecial(Transpose: true); //voila... :)
range.Delete(XlDeleteShiftDirection.xlShiftToLeft); //delete original range
if (!System.IO.File.Exists(savePath)) //is the workbook already saved?
{
excelApp.ActiveWorkbook.SaveAs(savePath); //save
}
else
{
Console.WriteLine("File \"{0}\" already exists.", savePath); //or do whatever...
Console.ReadLine();
return;
}
It could be simplified further... but it is more readable like this.
This was asked a long time ago but I will let my sollution anyway.
Refs:
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;
The trick here is to get the _Application Variable
in case you are using VSTO ADDIN with Workbook you can do like this:
var app = Globals.ThisWorkbook.Parent as _Application;
For other kind of project do like this:
_Application app2 = new Excel.Application();
My sample (sheet1 is my worksheet):
var sheet1 = Globals.Planilha1;
var arr = new string[]
{
"test1",
"test2",
"test3",
"test4",
"test5",
"test6",
};
// For VSTO ADDINS with Workbook
//var app = Globals.ThisWorkbook.Parent as _Application;
// For any kind of Excel Interop project
_Application app = new Excel.Application();
sheet1.Range["A1:A" + arr.Length].Value = app.WorksheetFunction.Transpose(arr);
The Transpose function can only deal with arrays, lists won't work.
Just place the array inside the app.WorksheetFunction.Transpose function and it will work pretty well.
Output:
I'm trying to read data from an Excel document in C# using Microsofts COM Interop.
So far, I'm able to load the document and read some data from it. However, I need to read data from two different columns and output these as json (for a jquery ajax call)
I've made a quick prototype of how my Excel document is structured with the hope that it's a bit easier to explain ;-)
The method I have is called GetExcelDataByCategory(string categoryName) where the categoryName parameter would be used to find which column to get the data from.
So, i.e., if I'm making the call with "Category 2" as parameter, I need to get all the values in the C columns rows and the corresponding dates from the A column, so the output will look like this:
Which then needs to be transformed/parsed into JSON.
I've searched high and low on how to achieve this, but with no luck so far :-( I'm aware that I can use the get_Range() method to select a range, but it seems you need to explicitly tell the method which row and which column to get the data from. I.e.: get_Range("A1, C1")
This is my first experience with reading data from an Excel document, so I guess there's a lot to learn ;-) Is there a way to get the output on my second image?
Any help/hint is greatly appreciated! :-)
Thanks in advance.
All the best,
Bo
This is what I would do:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open("path to book");
Excel.Worksheet xlSheet = xlWorkbook.Sheets[1]; // get first sheet
Excel.Range xlRange = xlSheet.UsedRange; // get the entire used range
int numberOfRows = xlRange.Rows.Count;
int numberOfCols = xlRange.Columns.Count;
List<int> columnsToRead = new List<int>();
// find the columns that correspond with the string columnName which
// would be passed into your method
for(int i=1; i<=numberOfCols; i++)
{
if(xlRange.Cells[1,i].Value2 != null) // ADDED IN EDIT
{
if(xlRange.Cells[1,i].Value2.ToString().Equals(categoryName))
{
columnsToRead.Add(i);
}
}
}
List<string> columnValue = new List<string>();
// loop over each column number and add results to the list
foreach(int c in columnsToRead)
{
// start at 2 because the first row is 1 and the header row
for(int r = 2; r <= numberOfRows; r++)
{
if(xlRange.Cells[r,c].Value2 != null) // ADDED IN EDIT
{
columnValue.Add(xlRange.Cells[r,c].Value2.ToString());
}
}
}
This is the code I would use to read the Excel. Right now it reads every column that has the heading (designated by whatever is in the first row) and then all the rows there. It isn't exactly what you asked (it doesn't format into JSON) but I think it is enough to get you over the hump.
EDIT: Looks like there are a few blank cells that are causing problems. A blank cell will be NULL in the Interop and thus we get errors if we try to call Value2 or Value2.ToString() since they don't exist. I added code to check to make sure that the cell isn't null before doing anything with it. It prevent the errors.
for Excel-parsing and creation you can use ExcelDataReader: http://exceldatareader.codeplex.com/
and for json you can use json.net: http://json.codeplex.com/
Both are fairly easy to use. Just have a look at the websites.
I'm getting result sets from Sybase that I return to a C# client.
I use the below function to write the result set data to Excel:
private static void WriteData(Excel.Worksheet worksheet, string cellRef, ref string[,] data)
{
Excel.Range range = worksheet.get_Range(cellRef, Missing.Value);
if (data.GetLength(0) != 0)
{
range = range.get_Resize(data.GetLength(0), data.GetLength(1));
range.set_Value(Missing.Value, data);
}
}
The data gets written correctly.
The issue is that since I'm using string array to write data (which is a mixture of strings and floats), Excel highlights every cell that contains numeric data with the message "Number Stored as Text".
How do I get rid of this issue?
Many thanks,
Chapax
Try the following: replace your array of string by an array of object.
var data = new object[2,2];
data[0, 0] = "A";
data[0, 1] = 1.2;
data[1, 0] = null;
data[1, 1] = "B";
var theRange = theSheet.get_Range("D4", "E5");
theRange.Value2 = data;
If I use this code, equivalent to yours:
var data = new string[2,2];
I get the same symptom as you.
As a side benefit, you don't have to cast anything to string: you can fill your array with whatever you want to see displayed.
Try setting the NumberFormat property on the range object.