C# EPPlus move "generated sum field" into columnfields - c#

I need to use epplus instead of interop and in my excel file there is one "field" in the pivot table I can not get a hold of...
!(https://imgur.com/EPIwKQU)
This "Values" field is automatically generated from my code and does not show up in any of the fields I am able to access so far. Not sure if it is a field anyway.
var filesField = pivotTable.Fields["Files"];
filesField.Name = "Files";
pivotTable.DataFields.Add(filesField);
var sizeField = pivotTable.Fields["Size"];
sizeField.Name = "Size";
pivotTable.DataFields.Add(sizeField);
This creates the fields I need for my pivot table/chart and from those this "Values" field in the picture is created.
With interop I did this:
Pivotfield datafield = pivotTable.PivotFields("Daten");
But this does not work with eeplus, since the field "Daten" is not there.
I am trying to something like this, but it also could be that here i need to access the chart by itself?
var datafield = // some code to catch this sum
pivotTable.ColumnFields.Add(datafield);

I finally found an answer to my question. Since this "Values" field is auto generated and i could not access it I tried something else.
Turns out this line:
pivotTable.DataOnRows = false;
did the trick.
Did not research it yet, but I thought I share the answer to my problem.

Related

How to put a table from excel into a scrollable list of items in C#?

I have a table in an excel sheet with two columns and about 400 rows. Very simple. All I want is to now put that data into a scrollable list on a form in winforms.
I've been at this for awhile and have become frustrated. Everything I find is showing me how to add an item to a listview one by one, I assume there's an easier way.
This list is static, it will never need to change. How would I do this?
Holding data in source code is generally not a good idea. I think, there is no such thing as 'never changes'. I understand you don't want to implement the Excel-Stuff, but you may put the data in a Json, whatever... and use it as resource.
Anyway, you can use Excel functions to prepare your data for copy-paste.
Sorry for the german Excel, I think the english name of the function would be 'Concatenate'
then you copy the cells and paste it in your Code (assuming your variable is called 'list' and it's instantinated already...)
don't forget about the extra parenthesis in the excel function for strings!
Try this:
Type ExcelType = Type.GetTypeFromProgID("Excel.Application");
dynamic Excel = Activator.CreateInstance(ExcelType);
int Index = 1;
Excel.WorkBooks.Open("Your workbooks file location here...");
do
{
listBox1.Items.Add(Excel.Range("A" + Index).Value);
Index += 1;
} while (Excel.Range("A" + Index).Value != null);
Excel.Quit();
Excel = null;

OpenXML excel sheet creation. Formula does not work automatically when I use Indirect to reference a list

I am creating an excel template using OpenXML through c# for users to populate and import into our system.
Part of the process is for the user to select options from dropdowns and hidden columns are populated with the Id's of those selections using VLOOKUP formula. All of the ones with direct list references work fine.
I have one instance where the selection from a list called "Application Group" drives what list is used in the next column called "Application". This is done using the INDIRECT function in excel and works fine. The problem comes when trying to get the id for the dynamic list. I will post the code below but put simply opening the excel and selecting an option from application group correctly puts the correct list in Application. Selecting application does not populate the applicationid column automatically. If I select the applicationid column to see the formula is is fine. If I click into the edit box at the top of excel and then tab out of it the formula then triggers and will work from then on. Once again this is a VLOOKUP using the INDIRECT to creat the reference to the list.
I've done a few tests and it seems the INDIRECT is the issue as if I hard code the list name the vlookup triggers as it should.
I also removed the substitute functions but this did not make any difference.
I've checked the calculation mode on the column and it is set to automatic.
I've already searched online but found nothing relevant
// Application Group
cell = new Cell() { CellReference = "AI" + rownumber };
cell.CellValue = new CellValue();
cellFormula = new CellFormula()
{
Text = "VLOOKUP(AH" + rownumber.ToString() + " ,ApplicationGroupList,2,FALSE)"
};
cell.CellFormula = cellFormula;
row.Append(cell);
// Application
cell = new Cell() { CellReference = "AK" + rownumber };
cell.CellValue = new CellValue();
cellFormula = new CellFormula()
{
Text = "VLOOKUP(AJ" + rownumber.ToString() + ",INDIRECT(SUBSTITUTE(SUBSTITUTE(AH" + rownumber.ToString() + ",\" \",\"\"),\"/\",\"\") & \"Id\") ,2,FALSE)"
};
cell.CellFormula = cellFormula;
row.Append(cell);
There are no error messages and the formula is correct as simply clicking in the edit box triggers the formula and it works from then on. It seems like excel is not recognising it as a formula even though it was set up in the same way as others that work fine. See the code above. Application group works fine. Application doesn't but the formula created is fine syntactically and functionally.
Does anyone have any experience of something similar and how to get the formula to work as all the others do.
Ok well as seems often to be the case I've spent ages looking at this myself. Exhausted all the options, or so I thought. Just after I post this I think I'll just try this thing I've not had to do for any of the other formula just in case. Bingo!
So I had to add
cellFormula.CalculateCell = true;
And this seemed to solve the problem. Why I needed it I don't know as everything else seems to work without explicitly setting this flag but problem seems to be solved.

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.

Read-Only merge fields in Word C#

I have a requirement to create read-only merge fields in Word.
I've already tried using the Locked property which can be seen below.The description of this property states - When a field is locked you cannot update field results which sounds like a perfect fit for my problem but this doesn't seem to be working
Below is the code i use to add the merge field to MS Word:
using Word = Microsoft.Office.Interop.Word;
Word.Range currentRange = Globals.ThisAddIn.Application.Selection.Range;
Word.MailMerge merge = Globals.ThisAddIn.Application.ActiveDocument.MailMerge;
merge.Fields.Add(currentRange, selectedNode.LocalName).Locked = true;
Once I run the code above and the field is created in Word, I am still able to right click it and select "Edit Field" where I can potentially rename the field or perform other changes without getting any errors or preventions from Word.
If anyone implemented something like this before, please share your knowledge.
Here is some insight on the technologies:
The solution is targeted at MS Word Office 2010
It must be written in .NET C# 3.5
Cannot use Open Xml SDK, the fix must be performed using Office Interop
The solution must achieve the desired goals without making the whole document read-only
Thank you for the replies, however I needed to only make the merge fields read-only the rest of the document should still stay as is.
A colleague of mine found a nice way to achieve what I was looking for, just sharing it in case someone else may need this functionality:
All you need to do is create a ContentControl object and add your merge field to the content control.
Set the LockContents property to true. This property is used to determine whether a user is allowed to edit the contents of a content control.
using Word = Microsoft.Office.Interop.Word;
object missing = System.Type.Missing;
Word.Selection PosRange = Globals.ThisAddIn.Application.Selection;
Microsoft.Office.Interop.Word.ContentControl cntCtrl;
cntCtrl = PosRange.Range.ContentControls.Add(Microsoft.Office.Interop.Word.WdContentControlType.wdContentControlRichText, ref missing);
object fldType = Microsoft.Office.Interop.Word.WdFieldType.wdFieldMergeField;
object fldText = "Employee";
Microsoft.Office.Interop.Word.Field fld = cntCtrl.Range.Fields.Add(cntCtrl.Range, ref fldType, ref fldText);
cntCtrl.LockContents = true;
In the image below a merge field is hosted inside a content control, note users are now unable to edit the field
Using the Locked property will only prevent the value of the field from changing, which I'm assuming is not what you want.
The only way I know to prevent the field code from changing is to protect the document. The fields themselves should still be updatable.

Programmatically managing Microsoft Access Attachment-typed field with .NET

Access added a new data type in the 2007 version--the Attachment type. We are currently working on a WinForms application with .NET 3.5 (C#) that uses an Access 2007 database. We want to be able to add new attachments through the WinForms interface. I can't seem to locate any information on how to insert or select attachment data with .NET. I did try using DAO (version 12) but it didn't seem to have the SaveToFile or LoadFromFile methods discussed here: http://msdn.microsoft.com/en-us/library/bb258184.aspx
So, how can I get at the attachments with .NET?
I finally got this working in C# using a reference to Microsoft.Office.Interop.Access.Dao.
DBEngine dbe = new DBEngine();
Database db = dbe.OpenDatabase("C:\\SomeDatabase.accdb", false, false, "");
Recordset rs = db.OpenRecordset("SELECT * FROM TableWithAttachmentField", RecordsetTypeEnum.dbOpenDynaset, 0, LockTypeEnum.dbOptimistic);
rs.MoveFirst();
rs.Edit();
Recordset2 rs2 = (Recordset2)rs.Fields["AttachmentFieldName"].Value;
rs2.AddNew();
Field2 f2 = (Field2)rs2.Fields["FileData"];
f2.LoadFromFile("C:\\test.docx");
rs2._30_Update();
rs2.Close();
rs._30_Update();
rs.Close();
This will add test.docx to the Attachment field "AttachmentFieldName" in table "TableWithAttachmentField". One thing to note is that attempting to add the same file twice will throw an error.
Interesting question. I don't use A2007, but have the runtime installed, so I used the Access object browser to see what's in there. I discovered something really odd -- there are two FIELD objects, Field and Field2. The attachment functions are members of Field2 but not Field. So, my suggestion would be that perhaps what you need to do is convert this:
Recordset.Fields("FileData").LoadFromFile(<filename>)
to something like this:
Dim rs As DAO.Recordset
Dim fld2 As DAO.Field2
Set rs = CurrentDb.OpenRecordset("[SQL]")
Set fld2 = Recordset.Fields("FileData")
fld2.LoadFromFile(<filename>)
rs.Close
Set fld2=Nothing
Now, I don't know if that will correct the problem for you, but it seems to me that given the two Field objects with different properties/methods/members, you need to be explicit about which Field object you're using. The code example you cite is specifically for use in Access and maybe Access does something to automatically resolve the differences between the two object (perhaps it uses the Field object by default for non-ACCDB databases and the Field2 object for ACCDB files).
Look at this write up on the Access team blog It has basically what David is suggesting with a bit of a twist. It sets a Recordset2 type object equal to the value of the attachment field. Then appends a record to that recordset a puts the file contents in that new record.
I've been struggling to try and do this same thing. There is a reference you can include in your project to "Microsoft.Office.Interop.Access.Dao" that will get you the Recordset2 and Field2 Interfaces, but no implementation classes.
That's about as far as I've gotten, I'll post more once/if I figure it out...
I was not able to get this working in C#, so I moved on to a different solution. I would love to know how to do this though if someone figures it out.

Categories