MS Word Table Cell with Different Formats - c#

I'm trying to automate a table cell format with VSTO. The output I'm looking for is:
Particularly note the difference in font size between the LineItem and LineItemDescirption tokens.
How can write these two different formats to the same cell within C#?
I currently have the following:
var r = table.Cell(row, 1).Range;
r.Text = item.Name + Environment.NewLine + item.Description;
r.Font.Size = 11;
But I can't find out how to do this as two separate entities. I thought Range.Sentences would help (to return different ranges I could then apply the style individually to) but the compiler complains it doesn't exist.
I can't seem to write two ranges to the same cell. I can only seem to capture the full text of any given range...
I'm (obviously) not fluent in the Word object model. If someone can give me a push in the right direction that'd be great. Thanks

Related

Setting colors of an entire Excel range to array of colors

I have an Excel.Range with 10 cells and I want to change its color by using a 0 based 2d array with 10 elements of Excel.XlRgbColor.
object[,] colorsTest = new object[10, 1]
{
{ Excel.XlRgbColor.rgbAliceBlue, Excel.XlRgbColor.rgbAliceBlue},
{ Excel.XlRgbColor.rgbAliceBlue, Excel.XlRgbColor.rgbAliceBlue}...
(8 more)
};
Excel.Range range = activeSheet.Range[activeSheet.Cells[1, 1], activeSheet.Cells[10, 1]];
But now when I try to set
range.Interior.Color = colorsTest;
I get a Type mistmatch error for some reason. When I try to set the range's value with the array, everything works like intended - I get the indexes of my colors pasted into the cells as values, like expected.
Any idea what could be causing this? I think the type is what it should be.
I have about 5000 rows this has to apply to so looping through them separately results in tragic performance.
Interesting idea but unfortunately it's not possible to set different color for each cell in a range they way you wanted to do that. I'm actually surprised you didn't get an error.
I also agree with "tragic performance" I guess we're talking about minutes here.
I see just a few options here
Copy format - if the colors are stable and you will always apply the same or just a few variation of them. I'd prepare the colored cells somewhere, like in range AA1:AA10 and when you want to apply the colors I'd just copy & paste format to your range
OpenXML - I believe it would be a way faster than accessing cells one by one but I assume you will code it for at least one day. I don't have too much experience with OpenXML SDK but from what I have done I can tell you it's pretty verbose

How is it (is it?) possible to prevent the PivotTablization of data to result in "#DIV/0!" and such when there is missing data?

I am generating a PivotTable which is comprised of monthly data for items (how many of this sold, how many of that sold, and related statistics). In some cases, though, there are no sales for a particular item in one or more months. In that case, there is no record that contains a "0" value, the record simply does not exist for the non-existent sale.
When such an item's data is displayed, the nonexistent data wreaks havoc. The screen shot below shows what happens when an item does have data for both months (APPLES, GALA 5#), and when it doesn't (APPLES, GALA 5#):
So as you can see, when the data is PivotTablized, rather than put a "0" in "Total Packages" and "Total Purchases" it leaves those cells blank and inserts a "#DIV/0!" in the "Sum of Average Price" cell - and then a "." in the "% of Total" cell.
This is not helpful or pleasing to the eye. I would like either a series of dashes in those cells or zeroes.
A workaround would be to create a row for each currently non-existent one in the source pivot data, but that seems unnecessary and kludgy in the extreme - I would have to determine which items had "missing" months and then supply them with those 0 values.
Is this really what I need to do? Please say it ain't so!
UPDATE
The proffered answer led me to experiment with what would happen by changing the PivotTable options Format vals. With this data to begin:
...I entered a question mark for err vals, and a dash for empty cells:
This caused the data to look like so:
Better, but still not quite what I want/expect. Since it's better, at least, I'd settle for a programmatic way to accomplish the same thing.
I wasn't expecting to see the "?" following some of the "good" values, though...
So what I may need is the programmatic equivalent of "for empty cells, show a dash" (which converts to 0 for int and $0 for decimal).
Pivot Tables can hide errors.
Right-click on your Pivot Table and select Pivot Table options. On the Layout and Format tab, under Format, look for For error values show.
This is not perfect ("pvt" is the PivotTable):
pvt.ErrorString = "";
pvt.DisplayErrorString = true;
...but it does blank out (except for a recalcitrant "." in the %" cell) the missing values:
I added another line of code to see what it would do:
pvt.NullString = "-";
...so I now have this:
pvt.ErrorString = "";
pvt.DisplayErrorString = true;
pvt.NullString = "-";
...and adding that last line did help - I get the "0" for ints and "$0" for decimals like so:

iTextSharp. How to get specific types from AcroFields? Like PushButtonField, RadioCheckField, etc

I am trying to cast AcroFields to the specific types so I can set properties on them.
When I call AcroFields.GetField(string name); all I get is a string.
When I call AcroFields.GetFieldItem(string name); I get an object but cannot cast it to the specific type.
I have also tried:
AcroFields.SetFieldProperty("myfield", "CheckType", RadioCheckField.TYPE_STAR, null);
This returned false every time.
To better explain my scenario:
I have an existing PDF ( I am NOT generating this file ).
There is a checkbox in it. I want to change the "CheckType" like this:
myRadioCheckField.CheckType = RadioCheckField.TYPE_STAR
But since I cannot cast the AcroField to the specific type I cannot access that property "CheckType".
Is there a way to achieve this?
Please provide a working sample if possible.
Thank you.
Your post contains two different questions. One question is easy to answer. The other question is impossible to answer.
Let's start with the easy question:
How to get specific types from AcroFields? Like PushButtonField, RadioCheckField, etc
This is explained in the FormInformation example, which is part of chapter 6 of my book:
PdfReader reader = new PdfReader(datasheet);
// Get the fields from the reader (read-only!!!)
AcroFields form = reader.AcroFields;
// Loop over the fields and get info about them
StringBuilder sb = new StringBuilder();
foreach (string key in form.Fields.Keys) {
sb.Append(key);
sb.Append(": ");
switch (form.GetFieldType(key)) {
case AcroFields.FIELD_TYPE_CHECKBOX:
sb.Append("Checkbox");
break;
case AcroFields.FIELD_TYPE_COMBO:
sb.Append("Combobox");
break;
case AcroFields.FIELD_TYPE_LIST:
sb.Append("List");
break;
case AcroFields.FIELD_TYPE_NONE:
sb.Append("None");
break;
case AcroFields.FIELD_TYPE_PUSHBUTTON:
sb.Append("Pushbutton");
break;
case AcroFields.FIELD_TYPE_RADIOBUTTON:
sb.Append("Radiobutton");
break;
case AcroFields.FIELD_TYPE_SIGNATURE:
sb.Append("Signature");
break;
case AcroFields.FIELD_TYPE_TEXT:
sb.Append("Text");
break;
default:
sb.Append("?");
break;
}
sb.Append(Environment.NewLine);
}
// Get possible values for field "CP_1"
sb.Append("Possible values for CP_1:");
sb.Append(Environment.NewLine);
string[] states = form.GetAppearanceStates("CP_1");
for (int i = 0; i < states.Length; i++) {
sb.Append(" - ");
sb.Append(states[i]);
sb.Append(Environment.NewLine);
}
// Get possible values for field "category"
sb.Append("Possible values for category:");
sb.Append(Environment.NewLine);
states = form.GetAppearanceStates("category");
for (int i = 0; i < states.Length - 1; i++) {
sb.Append(states[i]);
sb.Append(", ");
}
sb.Append(states[states.Length - 1]);
This code snippet stores the types of the fields in a StringBuilder, as well as the possible values of a radio field and a check box.
If you execute it on datasheet.pdf, you get form_info.txt as a result.
So far so good, but then comes the difficult question:
How do I find the check type? How do I change it?
That question reveals a lack of understanding of PDF. When we looked for the possible values of a check box (or radio button) in the previous answer, we asked for the different appearance states. These appearance states are small pieces of content that are expressed in PDF syntax.
For instance: take a look at the buttons.pdf form.
When we look at it on the outside, we see:
The check box next to "English" can be an empty square or a square with a pinkish background and a cross. Now let's take a look at the inside:
We see that this is the table check box, and we see that there are two appearance states: /Yes and /Off. What these states look like when selected, is described in a stream.
The stream of the /Off state is rather simple:
You immediately see that we are constructing a rectangle (re) and drawing it without filling it (S).
The /Yes state is slightly more complex:
We see that the fill color is being changed (rg), and that we stroke the rectangle in black and fill it using the fill color that was defined (B). Then we define two lines with moveTo (m) and lineTo (l) operations and we stroke them (S).
If you are proficient in PDF syntax, it is easy to see that we're drawing a cross inside a colored rectangle. So that answers your question on condition that you're proficient in PDF...
If you want to replace the appearance, then you have to replace the stream that draws the rectangle and the cross. That's not impossible, but it's a different question than the one you've posted.
Summarized: There is no such thing as a TYPE_STAR in the PDF reference (ISO-32000-1), nor in any PDF. If you have an existing PDF, you can not cast a check box or radio button to a RadioCheckField. You could try to reconstruct the RadioCheckField object, but if you'd want to know if a check box is visualized using a check mark, a star,... then you have to interpret the PDF syntax. If you don't want to do that, you can't create the "original" RadioCheckField object that was used to create the PDF due to the lack of ready-to-use information in the PDF.
After some research I have come to the conclusion that at this point in time, with the current version of iTextSharp v5.5.7.0:
It is NOT possible to grab an AcroField and cast it back to the original class ( RadioCheckField ) that was used to generate the field in the first place.
So the specific classes like PushButtonField and RadioCheckField are only useful for generating a new PDF but not for editing an existing PDF.
This cannot be done.
As far as I know iTextSharp does not support casting from AcroField back to the orginal class ( RadioCheckField ) that was used to generate the field.
You would have to write your own code to parse and inspect the PDF to achieve this.

Edit Range NumberFormat in existing document

I can't change column format in an existing Excel document (xlsx). Columns content are numbers actually but shown as text and therefore green triangle appear telling that cells shown as text.
So I open this document in C# app and do the following thing:
sheet_.Range[sheet_.Cells[1, 2], sheet_.Cells[rowNum, 2]].EntireColumn.NumberFormat = "0";
But it doesn't change column to appear content as numbers (they remain aligned by left side)
I know this is an old post, but I've been dealing with the same problem. I receive .xlsx files that already have green triangles denoting "Number as Text" errors. I couldn't find a way to programmatically run the Excel error-checking command "Convert to Number" that you can do by clicking in Excel, and changing the NumberFormat on cells with these errors didn't work for me, but I was able to "refresh" the cell format by using the TextToColumns method.
int lastCol = sheet.UsedRange.Columns.Count;
if(lastCol > 1)
{
for (int i = 1; i <= lastCol; i++)
{
sheet.Columns[i].TextToColumns(Type.Missing, XlTextParsingType.xlDelimited, XlTextQualifier.xlTextQualifierNone);
}
And from there you can change the NumberFormat. I happened to have long integers that were getting put into scientific notation, so I used this to make them regular integers again:
sheet.Cells.NumberFormat = "#";
(PS, if anyone finds a definitive guide on the symbols to use for customized NumberFormats, I'm still trying to find one!)
Try to access to cell value over get_Range method! for example and for what number format you want, lets say that you have in your excel cell this number : 1546,65
sheet_.get_Range("P10", "Q10").NumberFormat = "0"; // returns 1546
sheet_.get_Range("P10", "Q10").NumberFormat = "0,00"; // returns 1546,65
sheet_.get_Range("P10", "Q10").NumberFormat = "#.##0,00"; // returns 1.546,65
And you can play with these number formats!
Hope it helps you
I didn't find ideal solution to this issue and ended with the following:
sheet_.get_Range("A1", "A100").NumberFormat = "0";
for(int i = 1; i <= 100; i++)
{
sheet_.Cells[1, i].Value = sheet_.Cells[1, i].Value;
}
I know this is a old post but I stumbled over this and have a solution for this. Have you tried to not assign any NumberFormat? by default excel decides based on the cell content so you wouldnt get green triangle if you have numbers which are stored as text. If you want read values based on data type then refer this post
http://www.codeproject.com/Articles/335589/Export-Multiple-Datasets-to-Multiple-Excel-sheets
For me using the Style and the NumberFormatLocal solved the problem:
sheet_.get_Range("A1", "A100").Style.NumberFormatLocal = "0";

Can I set auto-width on an Open XML SDK-generated spreadsheet without calculating the individual widths?

I'm working on creating an Excel file from a large set of data by using the Open XML SDK. I've finally managed to get a functional Columns node, which specifies all of the columns which will actually be used in the file. There is a "BestFit" property that can be set to true, but this apparently does not do anything. Is there a way to automatically set these columns to "best fit", so that when someone opens this file, they're already sized to the correct amount? Or am I forced to calculate how wide each column should be in advance, and set this in the code?
The way I understand the spec and this MSDN discussion, BestFit tells you the width was auto-calculated in Excel, but it does not tell Excel that it should calculate it again next time it is opened.
As "goodol" indicates in that discussion, I think the width can only be calculated when you display the column, since it depends on the contents, the font used, other style parameters... So even if you want to pre-calculate the width yourself, be aware that this is only an estimation, and it can be wrong if the contents contain lots of "wide" characters. Or does the Open XML SDK do this for you?
I'm using EPPlus which I highly recommend. Took me a while to figure out how to do it using that, here's what I came up with:
// Get your worksheet in "sheet" variable
// Set columns to auto-fit
for (int i = 1; i <= sheet.Dimension.Columns; i++)
{
sheet.Column(i).AutoFit();
}

Categories