How to create a formula (SUBTOTAL) below table - c#

I use EPPLus to create a excel file with a table in it. Creating the excel file and table works like a charm using:
worksheet.Cells["A1"].LoadFromCollection(rows, true, TableStyles.Light12);
...but when I try to insert a formula into the first empty row after the table, the file becomes corrupt and cannot be opened normally. Excel can recover it though, but the formula I added will never show.
I use this line of code to create the formula:
worksheet.Cells["E"+(rows.Count+2).ToString()].Formula = "=SUBTOTAL(109;[TurnoverCurrent])";
I've already confirm that I'm targeting the correct cell, and if I insert just a string instead of a formula, it works. Hence my feeling is that I don't use the formula method correctly. How can I achieve a SUBTOTAL formula after my table?

Three things jump out at me, and I'm not sure if either/or will fix it, but I thought to offer.
1) your subtotal formula is right next to the table -- when Excel renders the XML, is it trying to add this to the table and freaking out because it's self-referencing? In other words, the subtotal formula is now part of the table and adding itself?
2) when I use subtotal, I use a comma, not a semicolon
3) you didn't reference the table name in your formula. Since this is a brand new sheet, it's safe to try Table1. If you really want to be fancy, you can look up the table and find its name. I wouldn't.
So maybe add one row, prefix the table name and change your semicolon to a comma?
worksheet.Cells[rows.Count + 3, 5].Formula = "=SUBTOTAL(109,Table1[TurnoverCurrent])";

Change
worksheet.Cells["E" + (rows.Count+2).ToString()].Formula = "=SUBTOTAL(109;[TurnoverCurrent])";
to
worksheet.Cells["E" + (rows.Count+2).ToString()].Formula = "SUBTOTAL(109;[TurnoverCurrent])";
Do nut use the "="

Related

Insert Excel Rows/Columns with ExcelDNA or NetOffice

I am using ExcelDNA to set and get cell values. I can get and set cell values
var ref = ExcelReference(2, 2);
var val = ref.GetValue();
ref.SetValue(42);
is there a way to insert an entire row or column by moving entries to the right or down? I want the same behavior as when the user right clicks the column and all the entries are shifted to the right. Solution can use NetOffice if necessary.
I'd recommend using the COM object model for this, and the code will be similar to VBA for the same task.
You get hold of the root Application object with a call to ExcelDnaUtil.Application. The resulting object will be of type Microsoft.Office.Interop.Excel.Application and can be used to select the row of column, then call app.Selection.Insert() to insert the new row or column.
It should also be possible using the C API, but that is unlikely to be easier or faster.
I would like to add that NetOffice does not support the EntireRow and EntireColumn methods of the Range object, which would be useful for inserting or deleting full rows. As a workaround, one can replace this for rows by addressing full rows by Range(rowNoStart + ":" + rowNoEnd).
For columns, one can write Range(GetExcelColumnName(colStart) + ":" + GetExcelColumnName(colEnd)), where GetExcelColumnName is a function from this former SO post.

How to eliminate trailing empty row/columns

I am using Microsoft Interop to convert excel files into csv files. I use sheet.SaveAs function.
My initial excel sheet has data from A1 to AZ columns for 100 rows.
I need in the CSV just the data from A1 to AP and only for 50 rows.
Using the Range function, I delete the row51-100, I clear the contents for the same rows, still when I save as CSV, I find rows 51-100 as below: (just commas). I do not want to see these commas in CSV.
,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,
The same for column AQ-AZ as well. I do not want these data in CSV. I delete, clear contents using Range function, yet these AQ-AZ columns appears in CSV files as “,,,,,,,,,,,,,,,,,,,,,” .
Is there a way to save XLS as CSV with only Range that I want to see in the CSV file. Is there a way to control the range that goes into CSV file?
In short, I want to see in CSV file just the data for column A1 to AP for 50 rows. No empty trailing “,”s. Is there a way?
The issue you are describing seems like a "Last Cell" issue. The last cell is the original end of your data, even after you delete rows/columns.
Here is what Microsoft has to say about it: How to reset the last cell in Excel
I seem to remember a programmatic way of doing this, but for the life of me, I cannot recall how.
Having looked at that info, maybe you could rethink how you can do this.
Perhaps you could just read the data you need and write it out yourself.
i.e. For each row in range, get the row as a value which will be an array of object,
convert to array of string, string.join with the delimiter as a comma and append
to a .csv file.
Clearing the contents as suggested in another answer did not work for me, what did work was copying the populated columns in a new worksheet and overwriting the old CSV.
Simply select the trailing empty columns in Excel, right click and select: clear contents. Then save.

Linq To excel cant find column in excel

I am using Linq to Excel library to get acces to one of excel sheets, the problem which i got into is, that my call cant fin a column with specifik name.
public IQueryable<Cell> getExcel()
{
var excel = new ExcelQueryFactory();
excel.FileName = #"C:\Users\Timsen\Desktop\QUOTATION.CSV";
var indianaCompanies = from c in excel.Worksheet() select c["ARTICLE TEXT"];
return indianaCompanies;
}
Error :
base {System.SystemException} = {"'ARTICLE TEXT' column name does not exist. Valid column names are 'QUOT NO;DEBTOR;ITEM;ART NO;HWS NO#;BRANCH PRICE;QTY;PR;ARTICLE T', 'F2', 'F3', 'F4', 'F5'"}
Name of tables in Excell
QUOT
NO
DEBTOR
ITEM
ART
NO
HWS
NO.
BRANCH PRICE
QTY
PR
ARTICLE TEXT
TYPE NAME
SALES PRICE
QT%
DIS
AMOUNT
UNI
B
ARTG
SUPPL
DUTY
UPDAte Sample of Excel :
Can you show us the first line or two of the csv file?
If I'm interpreting the error message correctly, the header line has semicolons instead of commas for separators.
Specifically, the error message appears to list these as the column names (note that it's using single quotes and commas to try and make it clear, which seems useful).
'QUOT NO;DEBTOR;ITEM;ART NO;HWS NO#;BRANCH PRICE;QTY;PR;ARTICLE T'
'F2'
'F3'
'F4'
'F5'
Since that first column name is 64 characters, I'm assuming it cut off at that point and the rest of the columns would be in there as well (still semicolon-delimited) if that limit wasn't in place.
Not sure off-hand if you can specify a different delimiter with the linq-to-excel project or not, since it appears to use Jet for csv files, as per https://github.com/paulyoder/LinqToExcel/blob/792e0807b2cf2cb6b74f55565ad700d2fcf31e19/src/LinqToExcel/Query/ExcelUtilities.cs
If making it a 'real' csv isn't an option and the library doesn't support specifying an alternate delimiter, you might just be able to get the articles text by going through the lines in the file (except the first) and pull out the 12th column (since that appears to be the article text).
So, something like:
var articleTextValues =
// Skip(1) since we don't want the header
from line in File.ReadAllLines(#"C:\Users\Timsen\Desktop\QUOTATION.CSV").Skip(1)
select line.Split(';')[11];
Change your code to this:
public IQueryable<Cell> getExcel()
{
var excel = new ExcelQueryFactory();
excel.FileName = #"C:\Users\Timsen\Desktop\QUOTATION.CSV";
var indianaCompanies = from c in excel.Worksheet() select c["ARTICLE T"];
return indianaCompanies;
}
It lists the valid column names. It is having problems with some of the headers for the columns indicated by the fact QTY;PR; means it parsed two different columns instead of one. F2 indicates it does not know what the header should actually be called.
The simplest solution is to verify the data being imported into the following query matches your excel document.
var indianaCompanies = from c in excel.Worksheet() select *;
I believe that will work.

How to Delete a Column Programmatically?

How does one delete a column (or multiple columns) in Excel?
eg. How to delete column C and shift the rest left?
Here is the solution to make it clearer (thanks to Leniel for the link)
Excel.Range range = (Excel.Range)sheet.get_Range("C1", Missing.Value);
range.EntireColumn.Delete(Missing.Value);
System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
This was the first result I hit and deleting a column in Excel doesn't need as much code as the current answers suggest. In fact (assuming you have a Worksheet object already, listed below as mySheet) all that is needed for the original question is:
mySheet.Columns["C"].Delete();
If you want to delete multiple columns then:
mySheet.Columns["C:D"].Delete();
You can specify a variable in the Delete method (see https://learn.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.xldeleteshiftdirection?view=excel-pia) i.e. mySheet.Columns["C"].Delete(xlShiftToLeft)but there's no need as the Delete method is smart enough to realise that the Range you are selecting is a single column, so will do this automatically.
You can also uses a numeric value to designate the column i.e. mySheet.Columns[2].Delete()
Here you find how to do it:
http://bytes.com/topic/c-sharp/answers/258110-how-do-you-delete-excel-column
http://quicktestprofessional.wordpress.com/2008/02/14/delete-columns-from-xl-sheet/

knowing if a string will be truncated when updating database

I'm working on a software that takes a csv file and put the data in a sqlserver. i'm testing it with bad data now and when i make a data string to long (in a line) to be imported in the database i got the error : String or binary data would be truncated the statement has been terminate. that's normal and that's what i should expect. Now i wanna detecte those error before the update to the database. Is there any clever way to detecte this?
The way my software work is that i importe every line in a dataset then show the user the data that will be imported. Then he can click a button to do the actual update. i then do a dataAdapter.Update( Dataset, "something" ) to make the update to the database.
The probleme is that the error row terminate all the update and report the error. So i want to detect the error before i do the update to the server so the other rows will be inserted.
thanks
You will have to check the columns of each row. See if one exceeds the maximum specified in the database, and if yes, exclude it from being inserted.
A different solution would be to explicitly truncate the data and insert the truncated content, which could be done by using SubString.
The only way that I know of is to pre-check the information schema for the character limit:
Select
Column_Name,
Character_Maximum_Length
From
Information_Schema.Columns
Where
Table_Name = 'YourTableName'
What you need is the column metadata.
MSDN: SqlConnection.GetSchema Method
Or, if you have opened a recordset on your database, another solution would be to browse the field object to use its length to truncate the string. For example, with ADO recordset/VB code, you could have some code like this one:
myRecordset.fields(myField) = left(myString, myRecordset.fields(myField).DefinedSize)

Categories