I have a feeling that this question is very simple, but I just can't find the answer.
I want to apply a column of formulas in column "C" based on information in col "A" and "B". I want the formula to work as it would in excel when you write a formula, and then drag, creating row-relative formulas all the way down.
The method below works, but it's very slow, since it writes each formula separately. I'm sure there's a more efficient method out there somewhere.
Thanks
using Excel = Microsoft.Office.Interop.Excel;
...
object oOpt = System.Reflection.Missing.Value; //for optional arguments
Excel.Application oXL = null;
Excel.Workbook oWB = null;
Excel.Worksheet oSheet = null;
Excel.Range oRng = null;
try
{
//Start Excel and get Application object.
oXL = new Excel.Application();
oXL.Visible = true;
//Get a new workbook.
oWB = (Excel.Workbook)(oXL.Workbooks.Add(Missing.Value));
oSheet = (Excel.Worksheet)oWB.ActiveSheet;
...
//Set numberOfRows
//Load information to column A and B
...
//Write the column of formulas
for (int r = 2; r < numberOfRows + 2; r++)
{
oRng = oSheet.get_Range("C" + r, "C" + r);
oRng.Formula = "= IF(AND(A" + r + "<> 0,B" + r + "<>2),\"YES\",\"NO\")";
}
}
catch (Exception theException)
{
String errorMessage;
errorMessage = "Error: ";
errorMessage = String.Concat(errorMessage, theException.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, theException.Source);
MessageBox.Show(errorMessage, "Error");
}
finally
{
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(oRng);
Marshal.FinalReleaseComObject(oSheet);
oWB.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(oWB);
oXL.Quit();
Marshal.FinalReleaseComObject(oXL);
}
Use R1C1 formula, and replace :
for (int r = 2; r < numberOfRows + 2; r++)
{
oRng = oSheet.get_Range("C" + r, "C" + r);
oRng.Formula = "= IF(AND(A" + r + "<> 0,B" + r + "<>2),\"YES\",\"NO\")";
}
with
oRng = oSheet.get_Range("C2").get_Resize(100, 1);
oRng.FormulaR1C1 = "=IF(AND(RC[-2]<> 0,RC[-1]<>2),\"YES\",\"NO\")";
I am posting this code for Drag formulas in excel from C# using Microsoft.Office.Interop.Excel Library
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Excel();
}
public void Excel()
{
Application xlApp = new Application();
Workbook xlWorkBook;
Worksheet xlWorkSheet;
object misValue = Missing.Value;
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.get_Item(1);
for (int r = 1; r < 5; r++) //r stands for ExcelRow and c for ExcelColumn
{
// Its a my sample example: Excel row and column start positions for writing Row=1 and Col=1
for (int c = 1; c < 3; c++)
{
if (c == 2)
{
if (r == 1)
{
xlWorkSheet.Cells[r, c].Formula = "=SUM(A1+200)";
}
continue;
}
xlWorkSheet.Cells[r, c] = r;
}
}
Range rng = xlWorkSheet.get_Range("B1");
// This is the main code we can Drag our excel sheet formulas in range
rng.AutoFill(xlWorkSheet.get_Range("B1", "B4"), XlAutoFillType.xlLinearTrend);
xlWorkBook.Worksheets[1].Name = "MySheetData";//Renaming the Sheet1 to MySheet
xlWorkBook.SaveAs(#"E:\test.xlsx");
xlWorkBook.Close();
Marshal.ReleaseComObject(xlWorkSheet);
Marshal.ReleaseComObject(xlWorkBook);
Marshal.ReleaseComObject(xlApp);
}
}
Related
I have the following code and I am trying to copy certain Range values from one Excel file to another.
I have managed to select the range from the first excel, but it does not "paste" it where I've selected the range to.
In this example, it copies it to the first cells in the second excel.
Could anyone help please?
Thank you!
Microsoft.Office.Interop.Excel.Application application = new Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[9];
Workbook workbook1 = application.Workbooks.Open(#"Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
object[,] valueArray = (object[,])range1.get_Value(XlRangeValueDataType.xlRangeValueDefault);
Range range2 = xlWorksheet1.get_Range("F1", "F5");
object[,] valueArray2 = (object[,])range2.get_Value(XlRangeValueDataType.xlRangeValueDefault);
for (int i = 2; i <= valueArray.GetLength(0); i++)
{
for (int j = 1; j <= valueArray.GetLength(1); j++)
{
for (int k = 1; k <= valueArray2.GetLength(0); k++)
{
for (int l = 1; l <= valueArray2.GetLength(1); l++)
{
valueArray2[i,j] = valueArray[i, j].ToString();
}
}
}
}
workbook1.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Solution
Microsoft.Office.Interop.Excel.Application application = new
Microsoft.Office.Interop.Excel.Application();
Workbook workbook = application.Workbooks.Open(#"D:\Excel.xlsx", 1);
Worksheet xlWorksheet = (Worksheet)workbook.Sheets[1];
Workbook workbook1 = application.Workbooks.Open(#"D:\Excel2.xlsx", 1);
Worksheet xlWorksheet1 = (Worksheet)workbook1.Sheets[1];
Range range1 = xlWorksheet.get_Range("C1", "C5");
Range range2 = xlWorksheet1.get_Range("F1", "F5");
range1.Copy(range2);
workbook1.Save();
workbook.Save();
workbook.Close();
workbook1.Close();
application.Quit();
Thank you!
I have some data saved in some strings, now I would like to open an existing Excel file, and write these strings in order in the empty cells after the populated ones,
Example:
I have the file that in column A is written up to 10, I would like the code to check that 10 finds a datum and writes to 11 and then continue [11, B] [11, C] until I finish the strings and then save the file.
I'm using Interop
using Microsoft.Office.Interop.Excel;
using Excel = Microsoft.Office.Interop.Excel;
OpenFileDialog FileExcel = new OpenFileDialog();
if (FileExcel.ShowDialog() == DialogResult.OK)
{
try
{
var sr = new StreamReader(FileExcel.FileName);
}
catch (SecurityException ex)
{
MessageBox.Show($"Security error.\n\nError message: {ex.Message}\n\n" +
$"Details:\n\n{ex.StackTrace}");
}
}
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(FileExcel.FileName);
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[Convert.ToInt32(comboBox1.SelectedItem)];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
//add useful things here!
}
}
I'm begining in WPF and i'm working with datagrid
I have multi datagrids. If i click a button ("Export" button) first time, it will create a new excel window and export data to first sheet. Then, i change to another datagrid and click a button ("Export" button) second time. so, it will create a new sheet in excel window which created before. Can you help me change my code ?
Thank you very much!!
public void Export(DataTable dt, string sheetName, string title)
{
Microsoft.Office.Interop.Excel.Application oExcel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks oBooks;
Microsoft.Office.Interop.Excel.Sheets oSheets;
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
Excel.Range _range = null;
oExcel.DisplayAlerts = false;
oExcel.Application.SheetsInNewWorkbook = 1;
oBooks = oExcel.Workbooks;
oBook = (Microsoft.Office.Interop.Excel.Workbook)(oExcel.Workbooks.Add(Type.Missing));
oSheets = oBook.Worksheets;
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(1);
oSheet.Name = sheetName;
Microsoft.Office.Interop.Excel.Range head = oSheet.get_Range("A1", "C1");
head.MergeCells = true;
head.Value2 = title;
head.Font.Bold = true;
head.Font.Name = "Tahoma";
head.Font.Size = "18";
head.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
List<object> objHeaders = new List<object>();
for (int n = 0; n <= dt.Rows.Count; n++)
{
objHeaders.Add(dt.Columns[n].ColumnName);
}
var headerToAdd = objHeaders.ToArray();
_range = oSheet.get_Range("A3", Type.Missing);
_range = _range.get_Resize(dt.Rows.Count, dt.Columns.Count);
_range.ColumnWidth = 30;
_range.set_Value(Type.Missing, headerToAdd);
Excel.Range rowHead = oSheet.get_Range("A3", "C"+dt.Columns.Count);
rowHead.Font.Bold = true;
rowHead.Borders.LineStyle = Microsoft.Office.Interop.Excel.Constants.xlSolid;
rowHead.Interior.ColorIndex = 15;
rowHead.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
int row = dt.Rows.Count;
int col = dt.Columns.Count;
object[,] arr = new object[row, col];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
int rowStart = 4;
int columnStart = 1;
int rowEnd = rowStart + dt.Rows.Count - 1;
int columnEnd = dt.Columns.Count;
Microsoft.Office.Interop.Excel.Range c1 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowStart, columnStart];
Microsoft.Office.Interop.Excel.Range c2 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowEnd, columnEnd];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
range.Borders.LineStyle = Microsoft.Office.Interop.Excel.Constants.xlSolid;
Microsoft.Office.Interop.Excel.Range c3 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[rowEnd, columnStart];
Microsoft.Office.Interop.Excel.Range c4 = oSheet.get_Range(c1, c3);
oSheet.get_Range(c3, c4).HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
oExcel.Visible = true;
}
}
You need to use field Microsoft.Office.Interop.Excel.Application oExcel in your class to store its value. First time it will be null, but on second - it will be opened excel. But you must be carefull with such a behavior, user can close excel, before 2nd export. So you need implement Closed event handler and clear your field (similar problem)
So, after much researching and using code below in a Class the items I'm passing (a DataTable) open up in Excel. I have around 5 sheets that need to open in the same book. The code below is for the first 2. The problem is they are all opening in NEW WorkBooks -- I need them all to open in the SAME WorkBook. They are opening on the correct sheet in each new Workbook though. I thought a simple "if" statement would work, however, it is not--
Any input on how to get them consolidated into one WorkBook would be greatly appreciated and thanks in advance!
Microsoft.Office.Interop.Excel.Application oExcel = new
Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks oBooks;
Microsoft.Office.Interop.Excel.Sheets oSheets;
Microsoft.Office.Interop.Excel.Workbook oBook;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
oExcel.Visible = true;
oExcel.DisplayAlerts = false;
oExcel.Application.SheetsInNewWorkbook = 5;
oBooks = oExcel.Workbooks;
oBook = (Microsoft.Office.Interop.Excel.Workbook)(oExcel.Workbooks.Add(Type.Missing));
oSheets = oBook.Worksheets;
if (sheetName == "Combined")
{
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(1);
oSheet.Name = sheetName;
object[,] arr = new object[dt.Rows.Count, dt.Columns.Count];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
Microsoft.Office.Interop.Excel.Range c1 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1, 1];
Microsoft.Office.Interop.Excel.Range c2 = (Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1 + dt.Rows.Count - 1, dt.Columns.Count];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
}
else if (sheetName == "Auto")
{
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oSheets.get_Item(2);
oSheet.Name = sheetName;
object[,] arr = new object[dt.Rows.Count, dt.Columns.Count];
for (int r = 0; r < dt.Rows.Count; r++)
{
DataRow dr = dt.Rows[r];
for (int c = 0; c < dt.Columns.Count; c++)
{
arr[r, c] = dr[c];
}
}
Microsoft.Office.Interop.Excel.Range c1 =
(Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1, 1];
Microsoft.Office.Interop.Excel.Range c2 =
(Microsoft.Office.Interop.Excel.Range)oSheet.Cells[1 + dt.Rows.Count - 1,
dt.Columns.Count];
Microsoft.Office.Interop.Excel.Range range = oSheet.get_Range(c1, c2);
range.Value2 = arr;
}
Well your code is a bit too long to understand without comments, but if you wanna add a new sheet inside your current workbook, there is the myWorkbook.Sheets.Add() method (where myWorkbook is a ref to your current workbook).
http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.sheets.add(v=office.14).aspx
I'm having some trouble reading from an Excel spreadsheet in C#.
I have this code which I read every cell from A to X.
System.Array myvalues; string[] strArray;
Microsoft.Office.Interop.Excel.Range range =
worksheet.get_Range("A" + i.ToString(), "W" + i.ToString());
while(range.Count!=0)
{
i++;
//Console.WriteLine(i);
range = worksheet.get_Range("A" + i.ToString(), "W" + i.ToString());
myvalues = (System.Array)range.Cells.Value;
strArray = ConvertToStringArray(myvalues);
name = clearstr(strArray[1]);
for ( int j = 1 ; j <= Int32.Parse(number_add_file)*4 ; j++)
{
name = "";
lang_add = "";
price = "";
description = "";
Console.WriteLine("I got in!");
Microsoft.Office.Interop.Excel.Range range_add =
worksheet.get_Range("X" + i.ToString(),Type.Missing);
System.Array values = (System.Array)range_add.Cells.Value;
string[] str = ConvertToStringArray(values);
name = str[0];
lang_add = str[1];
price = str[2];
description = str[3];
Console.WriteLine(name + " "
+ lang_add + " " + price + " " + description);
addfile();
}
My question is: How could i read next 4 * "number" rows in excel based on "number" value ?
For example:
A B C D E F G H I J
a a a a a 1 a a a a
F's cell value is 1 so I would like to read ( G H I J)
If F's cell value is 2 the I would like to read ( G H I J K L M N)
A B C D E F G H I J K L M N
a a a a a 2 a a a a a a a a
F's cell value 3 :
A B C D E F G H I J K L M N O P Q R
a a a a a 3 a a a a a a a a a a a a
This is for .NET 4.0:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open("somefile.xls");
Excel.Worksheet xlWorksheet = xlWorkbook.Sheets[1]; // assume it is the first sheet
Excel.Range xlRange = xlWorksheet.UsedRange; // get the entire used range
int value = 0;
if(Int32.TryParse(xlRange.Cells[1,6].Value2.ToString(), out value)) // get the F cell from the first row
{
int numberOfColumnsToRead = value * 4;
for(int col=7; col < (numberOfColumnsToRead + 7); col++)
{
Console.WriteLine(xlRange.Cells[1,col].Value2.ToString()); // do whatever with value
}
}
This will open the workbook and get the first worksheet in the workbook. We then get the entire used range and put that in the range variable. From there, we try to parse the int in column "F" (which is the 6th column, it is 1 based not zero based) in the first row. If that parsing is successful, we then multiply that number by 4 to see how many columns you need (in your post you said rows, but your examples were columns). We use a for loop to start at the G column (column 7) and go to the number of columns to read + 7 (to account for the columns that we skipped). You would be free to do what you want with the values but for this example I just wrote them to the console.
It is inot direct answer to your question, but you can easily refer to your cells like this:
int row1 = 1;
int row2 = 5;
sheet1.Cells[row1, row1+row2].Value=row1.ToString();
String Rng = Convert.ToString(sheet1.Cells[row1, row2-row1].Address());
string testList = "";
String str1 = "";
string logPath = #"E:\LogForConsoleApp.txt";
string filePath = #"E:\SaveSheetName.txt";
string Path = #"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\MSTest";
List<string> ltSheetName = new List<string>();
List<string> ltMethodName = new List<string>();
Process myProcess = new Process();
Excel.Application appExl = new Excel.Application();
Excel.Workbook workbook = null;
Excel.Worksheet NwSheet;
Excel.Range ShtRange;
appExl = new Excel.Application();
workbook = appExl.Workbooks.Open("E:\\inputSheet3", Missing.Value, ReadOnly: false);
NwSheet = (Excel.Worksheet)workbook.Sheets.get_Item(1);
ShtRange = NwSheet.UsedRange; //gives the used cells in sheet
int rCnt = 0;
int cCnt = 0;
for (rCnt = 1; rCnt <= ShtRange.Rows.Count; rCnt++)
{
for (cCnt = 1; cCnt <= ShtRange.Columns.Count; cCnt++)
{
if (Convert.ToString(NwSheet.Cells[rCnt, cCnt].Value2) == "Y")
{
ltSheetName.Add(NwSheet.Cells[rCnt, cCnt - 1].Value2);
//ltMethodName.Add(" /test:" + NwSheet.Cells[rCnt, cCnt - 1].Value2);
}
}
}
workbook.Close(false, Missing.Value, Missing.Value);
appExl.Quit();
for (int sht = 0; sht < ltSheetName.Count; sht++)
{
ltMethodName.Clear();
appExl = new Excel.Application();
workbook = appExl.Workbooks.Open(ltSheetName[sht].ToString(), Missing.Value, ReadOnly: false);
NwSheet = (Excel.Worksheet)workbook.Sheets.get_Item(1);
ShtRange = NwSheet.UsedRange; //gives the used cells in sheet
int rCnt1 = 0;
int cCnt1 = 0;
for (rCnt1 = 1; rCnt1 <= ShtRange.Rows.Count; rCnt1++)
{
for (cCnt1 = 1; cCnt1 <= ShtRange.Columns.Count; cCnt1++)
{
if (Convert.ToString(NwSheet.Cells[rCnt1, cCnt1].Value2) == "Y")
{
ltMethodName.Add(" /test:" + NwSheet.Cells[rCnt, cCnt - 1].Value2);
}
}
}
workbook.Close(false, Missing.Value, Missing.Value);
appExl.Quit();
for (int i = 0; i < ltMethodName.Count; i++)
{
str1 = ltMethodName[i].ToString();
testList += str1;
}
string foldername = "TestResult_" + DateTime.Today.ToString().Remove(DateTime.Today.ToString().LastIndexOf("/") + 5);
foldername = foldername.Replace("/", "");
string direc = #"E:\" + foldername;
string fileName = ltSheetName[sht].ToString().Substring(ltSheetName[sht].ToString().LastIndexOf("\\") + 1) + "_InderdeepAutRes.trx";
if (!Directory.Exists(direc))
Directory.CreateDirectory(direc);
string testcase = "";
if (!File.Exists(direc + "\\" + fileName))
testcase = " /testcontainer:" + "E:\\Practice\\TestingSample\\TestingSample\\bin\\Debug\\TestingSample.dll" + testList + " /resultsfile:" + direc + "\\" + fileName;
else
{
Directory.Delete(direc, true);
Directory.CreateDirectory(direc);
testcase = " /testcontainer:" + "E:\\Practice\\TestingSample\\TestingSample\\bin\\Debug\\TestingSample.dll" + testList + " /resultsfile:" + direc + "\\" + fileName;
}
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(Path, testcase);
try
{
TextWriter tw = new StreamWriter(filePath, false);
tw.WriteLine(ltSheetName[sht].ToString());
tw.Close();
myProcess.StartInfo = myProcessStartInfo;
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.RedirectStandardOutput = true;
myProcess.Start();
string output = myProcess.StandardOutput.ReadToEnd();
//myProcess.WaitForExit();
Console.WriteLine(output);
}
catch (Exception ex)
{
TextWriter tw = new StreamWriter(logPath, true);
tw.WriteLine(ex.StackTrace);
tw.Close();
}
}