I have an SSIS package which is populating an existing excel (template) with data via a Data Flow Task. The issue I am having is that I am dynamically creating worksheets and want to add a Hyperlink from the main page to the appropriate worksheet in that workbook.
I add the =Hyperlink reference to the appropriate sheet in the data flow task and it carries through just fine but the link (despite the column type being 'General') is not actually showing as a Hyperlink until I actually click in the cell, then it looks good.
I thought I could use a C# script task to flip the column to 'Text' and then back to 'General' and maybe that would make it read properly but no luck. Any ideas how I can simulate a double click in each of the cells in my column?
Here is what I have so far, which works for converting the column to general and wrapping text in another column but I am at a loss as to how to make this formula display properly as a Hyperlink.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
#endregion
namespace ST_2bdf93d5542441248076f053703d32c9
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
string inputFile = (string)Dts.Variables["RecommendationFileName"].Value;
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(inputFile);
ExcelApp.Visible = true;
Excel.Worksheet xlWorkSheetFocus = (Excel.Worksheet)ExcelWorkbook.Worksheets.get_Item(2);
xlWorkSheetFocus.Activate();
xlWorkSheetFocus.Select(Type.Missing);
Excel.Range usedRange = xlWorkSheetFocus.UsedRange;
xlWorkSheetFocus.Columns[5].NumberFormat = ""; //Make column 5 type General
xlWorkSheetFocus.Columns[4].WrapText = true; //Wrap text in column 4
ExcelWorkbook.Save();
GC.Collect();
GC.WaitForPendingFinalizers();
ExcelWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(ExcelWorkbook);
ExcelApp.Quit();
Marshal.FinalReleaseComObject(ExcelApp);
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
Well looks like I found a workable solution using text to columns, picking a delimiter "#" which doesn't exists, and writing the results to the same column/cell. Guessing there might be a better way but it gets me a clickable link.
xlWorkSheetFocus.get_Range("E6", ("E6" +
xlWorkSheetFocus.UsedRange.Rows.Count)).TextToColumns(Type.Missing,
Microsoft.Office.Interop.Excel.XlTextParsingType.xlDelimited,
Microsoft.Office.Interop.Excel.XlTextQualifier.xlTextQualifierNone, true,
Type.Missing, Type.Missing, false, true, Type.Missing,
"#", Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Related
I am trying to get a form that was created in visual studio WPF C# to submit to a new excel workbook will save onto a shared network drive. I have done a bit of digging trying to find the best solution and I have came across NPOI but all of the solutions seem pretty complicated compared to what I need to do. Is there some easy resource that I can reference to simply create a workbook and insert data into specific cells -- then save?
The two related packages I have seen in NuGet are DotNetCore.NPOI and NPOI which is the one I should be using?
What I have tried so far is:
private void Button_Click(object sender, RoutedEventArgs e)
{
using (var fs = new FileStream("Result12345.xlsx", FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Sheet1");
workbook.Write(fs);
MessageBox.Show("Form submitted successfully");
}
}
This gets outputted to : Project Folder \bin\Debug\net6.0-windows and it seems to create the workbook and save (assuming all I need to do is put in the path of the network drive in the file stream then that should be easy) but how do i insert data into cells specific cells?
I have worked with Microsoft Excel via interop COM libraries and should be directly available within your WPF app by adding as reference.
First, in the solution explorer, open the references, right-click and add reference.
Then, pick the Office libraries you are interested in working with, now or future, such as other apps too.
At the top of whatever code, you will then add the "using" clauses
using Microsoft.Office.Interop.Excel;
using System;
And here is a sample code snippet so you have control of whatever active workbook, worksheet, looping through explicit rows/columns and also getting the text of a given cell.
public void tryingExcel()
{
var SomeSampleFile = #"C:\Users\Public\SomeExcelFile.xlsx";
//Start Excel and get Application object.
var XL = new Microsoft.Office.Interop.Excel.Application();
XL.DisplayAlerts = false;
XL.Workbooks.Add();
// _Workbook and _Worksheet are part of Microsoft.Office.Interop.Excel
// via "using" clause at top of code
_Workbook wb = XL.ActiveWorkbook;
wb.Sheets.Add();
_Worksheet ws = wb.ActiveSheet;
ws.Cells[2, 1] = "Date/Time:";
ws.Cells[2, 2] = DateTime.Now;
for (var ir = 4; ir < 10; ir++)
ws.Cells[ir, 2] = "testing " + ir;;
for (var ir = 4; ir < 10; ir++)
ws.Cells[ir, 4] = ws.Cells[ir, 2].Text.Trim();
XL.ActiveWorkbook.SaveAs(SomeSampleFile, XlFileFormat.xlOpenXMLWorkbook,
Type.Missing, Type.Missing, false, false,
XlSaveAsAccessMode.xlNoChange,
XlSaveConflictResolution.xlLocalSessionChanges,
Type.Missing, Type.Missing, Type.Missing, false);
XL.Quit();
}
I have figured it out like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
using (var fs = new FileStream(#"\\ipaddress\sharename\Result12345.xlsx", FileMode.Create, FileAccess.Write))
{
IWorkbook workbook = new XSSFWorkbook();
ISheet excelSheet = workbook.CreateSheet("Sheet1");
//define cell to insert into
var cellTest = excelSheet.CreateRow(0).CreateCell(0);
//set cell value
cellTest.SetCellValue("Hello?");
//save the excel sheet
workbook.Write(fs);
MessageBox.Show("Form submitted successfully");
}
}
I guess I just didn't understand why I have to create a row / cell when they already exist. Rather than setting something like Cell(0,1).value = "Something"
I am using oledb to read .xls files in my application. It is working fine but real issue comes when my excel contains merged cells in rows or in column.
This is the data in excel
This is how it show on screen using webgrid
The VERY first thing that I would say is STAY VERY FAR AWAY FROM MERGED CELLS IN EXCEL!! That is the work of the DEVIL. Ok, if you still want to do this, consider the following options (you don't have many options) . . .
using Spire.Xls;
namespace Detect_Merged_Cells
{
class Program
{
static void Main(string[] args)
{
Workbook workbook = new Workbook();
workbook.LoadFromFile("Sample.xlsx");
Worksheet sheet = workbook.Worksheets[0];
CellRange[] range = sheet.MergedCells;
foreach (CellRange cell in range)
{
cell.UnMerge();
}
workbook.SaveToFile("Output.xlsx",ExcelVersion.Version2010);
}
}
}
OR
Excel.Range firstCell = excelWorksheet.get_Range("A1", Type.Missing);
Excel.Range lastCell = excelWorksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
object[,] cellValues;
object[,] cellFormulas;
Excel.Range worksheetCells = excelWorksheet.get_Range(firstCell, lastCell);
cellValues = worksheetCells.Value2 as object[,];
cellFormulas = worksheetCells.Formula as object[,];
As part of an ETL process I am importing data from a variety of different Excel files into a database. Before this happens I need to be able to change the cell format of all cells in an excel worksheet to be in the "General" format.
I have made a start but I'm afraid I dont know how to progress after this:
using Excel = Microsoft.Office.Interop.Excel;
.
.
.
String FilePath = "Code to get file location from database"
String SheetName = "Code to get SheetName from database"
Excel.Application MyApp = new Excel.Application();
MyApp.Visible = false;
Excel.Workbook myWorkbook = MyApp.Workbooks.Open(FilePath,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing);
//Code here to convert all rows to data type of general and then save
MyApp.Workbooks.Close();
Any help on this would be greatly appreciated
You can use Range.NumberFormat property:
var myWorksheet = (Excel.Worksheet)myWorkbook.Worksheets[1];
myWorksheet.Cells.NumberFormat = "General";
Please note that this may cause problems if your sheet contains date values.
I am trying to add a new worksheet to an Excel workbook and make this the last worksheet in the book in C# Excel Interop.
It seems really simple, and I thought the below code would do it:
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var excel = new Excel.Application();
var workbook = excel.Workbooks.Open(#"C:\test\Test.xlsx");
workbook.Sheets.Add(After: workbook.Sheets.Count);
workbook.Save();
workbook.Close();
Marshal.ReleaseComObject(excel);
}
}
}
No such luck. I get this helpful error:
COMException was unhandled - Exception from HRESULT: 0x800A03EC
I found this page on Microsoft.com which suggested I try and add the sheet first and then move it so I tried that as shown below. I know that this webpage targets Excel 95 but the VBA is still there to use so I was hoping it would still work:
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var excel = new Excel.Application();
var workbook = excel.Workbooks.Open(#"C:\test\Test.xlsx");
workbook.Sheets.Add();
workbook.Sheets.Move(After: workbook.Sheets.Count);
workbook.Save();
workbook.Close();
Marshal.ReleaseComObject(excel);
}
}
}
I get the same error as above. I have also tried passing the name of my last worksheet as a string as the After parameter in both the Add and Move methods, no joy!
That is what I have tried, so my question is how do I add a worksheet to an Excel workbook and make this the last sheet in the workbook using C# Excel Interop?
Thanks
Looking at the documentation here http://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.worksheet.move(v=vs.80).aspx, it indicates that the 'after' object isn't a numerical position; it's the object representing the sheet you want to position your sheet after. The code should probably be something like (untested):
workbook.Sheets.Add(After: workbook.Sheets[workbook.Sheets.Count]);
This should do the job:
wSheet.Move(Missing.Value, workbook.Sheets[workbook.Sheets.Count]);
This is the only way that works for me:
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.Add
(System.Reflection.Missing.Value,
xlWorkBook.Worksheets[xlWorkBook.Worksheets.Count],
System.Reflection.Missing.Value,
System.Reflection.Missing.Value);
it works for me
WorkBook.Worksheets.Add(
System.Reflection.Missing.Value,
WorkBook.Worksheets[WorkBook.Worksheets.Count],
1,
System.Reflection.Missing.Value);
I am trying to export data from dataset to excel and save it directly to a given path without giving me the option to open,save or cancel.
Using ExcelLibrary this is a one liner ...
DataSet myDataSet;
... populate data set ...
ExcelLibrary.DataSetHelper.CreateWorkbook("MyExcelFile.xls", myDataSet);
See also Create Excel (.XLS and .XLSX) file from C#
This C# Excel library can also be used to export the dataset. More details about how to export can be found here.
ExcelDocument xls = new ExcelDocument();
xls.easy_WriteXLSFile_FromDataSet("ExcelFile.xls", dataset,
new ExcelAutoFormat(Styles.AUTOFORMAT_EASYXLS1), "Sheet Name");
It's not the greatest solution but here is what I did, it opens a new excel document then copies what is in the dataset, all you need to do is sort out the columns and save it.
Btw totes my first post to answer a question, hope it helps
private void cmdExport_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("excel.exe");
try
{
copyAlltoClipboard();
Microsoft.Office.Interop.Excel.Application xlexcel;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlexcel = new Excel.Application();
xlexcel.Visible = true;
xlWorkBook = xlexcel.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
CR.Select();
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);
}
catch (Exception ex)
{
MessageBox.Show("Error :" + ex.Message);
}
}
private void copyAlltoClipboard()
{
dataGridViewItems.SelectAll();
DataObject dataObj = dataGridViewItems.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Check this DataSetToExcel
and c# (WinForms-App) export DataSet to Excel
In the first link change the code as follows:
Remove the all code that initially starts and try the following
using (StringWriter sw = new StringWriter("Your Path to save"))
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
}
}
Here's another C# library, which lets you export from a DataSet to an Excel 2007 .xlsx file, using the OpenXML libraries.
http://www.mikesknowledgebase.com/pages/CSharp/ExportToExcel.htm
All of the source code is provided, free of charge, along with a demo application, and you can use this in your ASP.Net, WPF and WinForms applications.
Once you've added the class to your application, it just takes one function call to export your data into an Excel file.
CreateExcelFile.CreateExcelDocument(myDataSet, "C:\\Sample.xlsx");
It doesn't get much easier than that.
Good luck !
Hi i found a perfect solution Here
Just replace 'missing.value' with System.Type.Missing in the code. Also remove
oWB.Close(System.Type.Missing, System.Type.Missing, System.Type.Missing);
and
oXL.Quit();
from the code. Otherwise your excel will get closed automatically as soon as it open.