Instantiating an Excel function - c#

Everywhere I look for how to use excel function inside of a C# application tells me to do the following:
From the COM TabAdd the following using statement:using IExcel = Microsoft.Office.Interop.Excel
Then declare and initialise a IWorkSheetFunction objectIExcel.IWorksheetFunction iwf = new IExcel.IWorksheetFunction();
Now you can use the functions as in int result = iwf.Math.Sum(1,2);
The problem im having is that while intellisense is detecting IExcel, it is not showing IWorksheetFunction. It is however showing WorksheetFunction. Either way, it is not letting me instantiate it as an object. I am getting the error: Cannot create an instance of the abstract class or interface 'Microsoft.Office.Interop.Excel.WorksheetFunction'
any ideas?

Try:
Microsoft.Office.Interop.Excel.Application xl = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.WorksheetFunction wsf = xl.WorksheetFunction;
int result = wsf.Percentile(obj, 0.75);
Basically it comes down to, instead of:
IExcel.IWorksheetFunction iwf =
new IExcel.IWorksheetFunction(); // You can't instantiate an interface
use the WorksheetFunction property in Excel.Application:
IExcel.IWorksheetFunction iwf = xl.WorksheetFunction;

Its a function off the application object.
using Microsoft.Office.Interop.Excel;
static void Main(string[] args)
{
Application a = new Application();
double x = a.WorksheetFunction.Sum(1, 2);
Console.WriteLine("Sum = {0}", x);
}

Related

How to write data to an existing Excel doc in C#

I have a document that I need to update on a monthly basis and I'm writing an automation to do so. This is my first time attempting to update a document with C# as opposed to simply creating a new one. I have researched and tried implementing a few libraries that I've found online and here on StackOverflow, for example, ClosedXML, but so far I've had no luck. I understand this question has been asked here before, so my actual question is: Is my implementation incorrect/am I doing something wrong?
public void WriteToReport(List<BrandData> brandData, string reportFilePath)
{
using (var workbook = new XLWorkbook(reportFilePath))
{
var worksheet = workbook(1);
worksheet.Cell(26, 2).Value = "Hello World!";
workbook.SaveAs(reportFilePath);
}
}
Above is how I've tried to test ClosedXML so far. The GitHub docs imply that it should be this simple, but I don't see any changes made to the doc when the automation is finished. I've also tried using Streamwriter. If anyone can help me with ClosedXML or suggest another library that worked for them, it would be greatly appreciated.
Edit: Following explanations on other similar questions on here, I have tried this:
public void WriteToReport(List<BrandData> brandData, string reportFilePath)
{
var workbook = new XLWorkbook(reportFilePath);
var worksheet = workbook.Worksheet(1);
int numberOfLastColumn =
worksheet.LastColumnUsed().ColumnNumber();
IXLCell newCell = worksheet.Cell(numberOfLastColumn + 1, 1);
newCell.SetValue("Hello World");
workbook.SaveAs(reportFilePath);
}
Here is a simple example to write a string value to the first WorkSheet.
public void WriteToCell(string fileName, int row, int col, string value)
{
using var workbook = new XLWorkbook(fileName);
var worksheet = workbook.Worksheets.Worksheet(1);
worksheet.Cell(row, col).Value = value;
workbook.SaveAs(fileName);
}

Visual studio C# VSTO: Refactoring

Coming from Visual basic, I kind of miss the With statement that is lacking in C#, I'm looking for ways to refactor the code so it's not so crowded.
I have the following code:
Globals.Ribbons.RibbonMain.chkCalculation.Checked = (Globals.ThisAddIn.Application.Calculation == Microsoft.Office.Interop.Excel.XlCalculation.xlCalculationAutomatic);
Globals.Ribbons.RibbonMain.chkScreenUpdating.Checked = Globals.ThisAddIn.Application.ScreenUpdating;
Globals.Ribbons.RibbonMain.chkEvents.Checked = Globals.ThisAddIn.Application.EnableEvents;
Globals.Ribbons.RibbonMain.chkDisplayAlerts.Checked = Globals.ThisAddIn.Application.DisplayAlerts;
How can I extract the common denominators to trim down the code to make it more legible?
What I thought is creating the 2 variables below, but i don't know the variable type I should use. Is there somewhere I could look for the variable type?
variableType R = Globals.Ribbons.RibbonMain
variableType A = Globals.ThisAddIn.Application
var should work fine, let the compiler figure out the type:
var R = Globals.Ribbons.RibbonMain;
var A = Globals.ThisAddIn.Application;
R.chkCalculation.Checked = (A.Calculation == Microsoft.Office.Interop.Excel.XlCalculation.xlCalculationAutomatic);
R.chkScreenUpdating.Checked = A.ScreenUpdating;
R.chkEvents.Checked = A.EnableEvents;
R.chkDisplayAlerts.Checked = A.DisplayAlerts;
Thank you #madreflection for sharing the knowledge.
As I'm using the 2 variables in multiple places, I extracted them as Static variables.
using EXCEL = Microsoft.Office.Interop.Excel;
internal class clsMacros
{
//GLOBAL VARIABLES
static RibbonMain RIBBON = Globals.Ribbons.RibbonMain;
static EXCEL.Application APPLICATION = Globals.ThisAddIn.Application;
public static void GetStatus()
{
RIBBON.chkCalculation.Checked = (APPLICATION.Calculation == EXCEL.XlCalculation.xlCalculationAutomatic);
RIBBON.chkScreenUpdating.Checked = APPLICATION.ScreenUpdating;
RIBBON.chkEvents.Checked = APPLICATION.EnableEvents;
RIBBON.chkDisplayAlerts.Checked = APPLICATION.DisplayAlerts;
}
}

How to use C# code to create an Excel sheet that contains a pivot table which has direct connection to my database using a query?

I am using Microsoft.Office.Interop.Excel dll, and I want to create an excel sheet which gets data from database using a query, either in the form of pivot tables or in the form of Data Table.
I don't want to get data using my C# code and then insert into Excel Sheet. I want my Excel sheet that has been generated to have a connection directly to database using that query. Is it possible and how to do it?
Please help.
Okay, how about this?
using Microsoft.Office.Interop.Excel;
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var connection = #"OLEDB;Provider=SQLOLEDB.1;Integrated Security=SSPI;Data Source=MYDATASOURCE;Initial Catalog=AdventureWorks2017";
var command = "SELECT * FROM [Sales].[vSalesPersonSalesByFiscalYears]";
var xl = new Application
{
Visible = true
};
xl.Workbooks.Add();
var pivotCache = xl.ActiveWorkbook.PivotCaches().Add(XlPivotTableSourceType.xlExternal, null);
pivotCache.Connection = connection;
pivotCache.MaintainConnection = true;
pivotCache.CommandText = command;
pivotCache.CommandType = XlCmdType.xlCmdSql;
var sheet = (Worksheet)xl.ActiveSheet;
var pivotTables = (PivotTables)sheet.PivotTables();
var pivotTable = pivotTables.Add(pivotCache, xl.ActiveCell, "PivotTable1");
pivotTable.SmallGrid = false;
pivotTable.ShowTableStyleRowStripes = true;
pivotTable.TableStyle2 = "PivotStyleLight1";
PivotField pageField = (PivotField)pivotTable.PivotFields("SalesTerritory");
pageField.Orientation = XlPivotFieldOrientation.xlPageField;
PivotField rowField = (PivotField)pivotTable.PivotFields("FullName");
rowField.Orientation = XlPivotFieldOrientation.xlRowField;
pivotTable.AddDataField(pivotTable.PivotFields("2004"), "Sum of 2004", XlConsolidationFunction.xlSum);
}
}
}
For demonstration purposes, I used a console app, but adapt it to fit whatever way you're working with the code.
I don't pretend to have originated all this code, I adapted it from:
Creating a PivotTable programmatically
updating it for AdventureWorks2017 and Excel Interop.

Excel interop doesn't accept ranges with commas

According to the documentation of Workbook.Range, you can provide commas in the first argument to provide an union.
However, the following code throws a COMException with HRESULT 0x800A03EC on the line that gets the range:
using Microsoft.Office.Interop.Excel;
public void RangeWithCommas() {
var excel = new Application();
var wb = excel.Workbooks.Add(xlWBATemplate.xlWBATWorksheet);
var ws = (Worksheet)wb.Worksheets[1];
var range = ws.Range["A1,A2"]; // this throws an exception
Console.WriteLine(range.Address[false,false]);
ws.Delete();
wb.Close(false);
excel.Quit();
}
How can I do or fix this?
P.S. I am aware of Application.Union but I would very much prefer not to use it because there is no easy way to provide a variable number of arguments.
As AnalystCave.com pointed out, some Excel COM methods are locale specific. You need to use the regional list seperator when accessing the COM method.
This code should work correctly on all locales:
using Microsoft.Office.Interop.Excel;
public void RangeWithCommas() {
var excel = new Application();
var wb = excel.Workbooks.Add(xlWBATemplate.xlWBATWorksheet);
var ws = (Worksheet)wb.Worksheets[1];
var rangestring = String.Join((string)excel.International[XlApplicationInternational.xlListSeparator], new [] {"A1","A2"});
var range = ws.Range[rangestring];
Console.WriteLine(range.Address[false,false]);
ws.Delete();
wb.Close(false);
excel.Quit();
}

Different class name in WinForm and WebService

I have a class defined that I use for loading information of the database as BO. I use the same DLL (I have it in a different project) for both, the WinForm app and the WebService.
The problem is that when I retrieve the info executing the WS, the name of the class comes with the namespace and the WS name included, and makes me convert from one object to another... but IS THE SAME!!!
List<**Trevo.FrameWork.MiAutoWS.ParametrosBOL**> oWs = obj.Parametros();
List<**ParametrosBOL**> x = new List<ParametrosBOL>();
foreach (Trevo.FrameWork.MiAutoWS.ParametrosBOL o in oWs)
{
ParametrosBOL oNuevo = new ParametrosBOL();
oNuevo.IDEmpresa = o.IDEmpresa;
oNuevo.IDTipo = o.IDTipo;
oNuevo.Tipo = o.Tipo;
oNuevo.IDCodigo = o.IDCodigo;}
}
Is there any way to avoid this?
Thanks in advance.

Categories