How to add border to cell with openxml in PowerPoint? - c#

I am trying to change the top border of a table in PowerPoint via OpenXml, but it has not worked for me. The cell currently has a left, right, and bottom border, but when I try to copy the bottom border and add it to the top border, PowerPoint does not reflect the change.
What do I need to change or am I doing wrong to make it work?
I currently have the following code to copy the bottom border and replace it.
BottomBorderLineProperties btp = (BottomBorderLineProperties)celda.TableCellProperties.BottomBorderLineProperties.CloneNode(true);
TopBorderLineProperties tbp = new TopBorderLineProperties()
{
Alignment = btp.Alignment,
CapType = btp.CapType,
CompoundLineType = btp.CompoundLineType,
MCAttributes = btp.MCAttributes,
Width = btp.Width
};
foreach(OpenXmlElement element in btp.ChildElements)
{
tbp.Append(element.CloneNode(true));
}
celda.TableCellProperties.TopBorderLineProperties = tbp;
Thanks!
PS: Sorry for my english

In order to set the top border of a cell in the middle of a PowerPoint table, you have to complete 2 steps:
Step 1: set the bottom border of the cell directly above the cell in question and
Step 2: set the top border of the cell in question (you have that part)
I determined this by using the OpenXML Productivity Tool. I took a simple 1 slide PowerPoint file named Before.pptx with a table cell that had the left, bottom and right borders.
Then I added the top border (using PowerPoint 2016) and saved the file as After.pptx. I then used the Productivity Tool to diff the 2 files and reverse engineer the C# code required to make Before.pptx look like After.pptx. The important code you need is displayed here:
//STEP 1 CODE STARTS HERE
A.Table table1=graphicData1.GetFirstChild<A.Table>();
A.TableRow tableRow1=table1.GetFirstChild<A.TableRow>();
A.TableRow tableRow2=table1.Elements<A.TableRow>().ElementAt(1);
A.TableCell tableCell1=tableRow1.Elements<A.TableCell>().ElementAt(2);
A.TableCellProperties tableCellProperties1=tableCell1.GetFirstChild<A.TableCellProperties>();
A.BottomBorderLineProperties bottomBorderLineProperties1 = new A.BottomBorderLineProperties(){ Width = 12700, CapType = A.LineCapValues.Flat, CompoundLineType = A.CompoundLineValues.Single, Alignment = A.PenAlignmentValues.Center };
A.SolidFill solidFill1 = new A.SolidFill();
A.SchemeColor schemeColor1 = new A.SchemeColor(){ Val = A.SchemeColorValues.Text1 };
solidFill1.Append(schemeColor1);
A.PresetDash presetDash1 = new A.PresetDash(){ Val = A.PresetLineDashValues.Solid };
A.Round round1 = new A.Round();
A.HeadEnd headEnd1 = new A.HeadEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
A.TailEnd tailEnd1 = new A.TailEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
bottomBorderLineProperties1.Append(solidFill1);
bottomBorderLineProperties1.Append(presetDash1);
bottomBorderLineProperties1.Append(round1);
bottomBorderLineProperties1.Append(headEnd1);
bottomBorderLineProperties1.Append(tailEnd1);
tableCellProperties1.Append(bottomBorderLineProperties1);
//STEP 1 CODE ENDS HERE
//STEP 2 CODE STARTS HERE
A.TableCell tableCell2=tableRow2.Elements<A.TableCell>().ElementAt(2);
A.TableCellProperties tableCellProperties2=tableCell2.GetFirstChild<A.TableCellProperties>();
A.BottomBorderLineProperties bottomBorderLineProperties2=tableCellProperties2.GetFirstChild<A.BottomBorderLineProperties>();
A.TopBorderLineProperties topBorderLineProperties1 = new A.TopBorderLineProperties(){ Width = 12700, CapType = A.LineCapValues.Flat, CompoundLineType = A.CompoundLineValues.Single, Alignment = A.PenAlignmentValues.Center };
A.SolidFill solidFill2 = new A.SolidFill();
A.SchemeColor schemeColor2 = new A.SchemeColor(){ Val = A.SchemeColorValues.Text1 };
solidFill2.Append(schemeColor2);
A.PresetDash presetDash2 = new A.PresetDash(){ Val = A.PresetLineDashValues.Solid };
A.Round round2 = new A.Round();
A.HeadEnd headEnd2 = new A.HeadEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
A.TailEnd tailEnd2 = new A.TailEnd(){ Type = A.LineEndValues.None, Width = A.LineEndWidthValues.Medium, Length = A.LineEndLengthValues.Medium };
topBorderLineProperties1.Append(solidFill2);
topBorderLineProperties1.Append(presetDash2);
topBorderLineProperties1.Append(round2);
topBorderLineProperties1.Append(headEnd2);
topBorderLineProperties1.Append(tailEnd2);
tableCellProperties2.InsertBefore(topBorderLineProperties1,bottomBorderLineProperties2);
I ran the code above against my Before.pptx file and the border was complete.
In an effort to double check that the two steps are necessary, I commented out the Step 1 code and ran it against a fresh version of Before.pptx file and the top border was missing. This verifies the problem you were seeing. Therefore, the two steps are necessary to paint the one border.

Related

Saving chart into image file with axis

can you tell me what is wrong with my code? I want to generate chart image in console application over System.Windows.Forms.DataVisualization.Charting library... Following code generate me chart only with columns, but I need chart with axis. Any ideas?
Chart chart = new Chart();
chart.Size = new System.Drawing.Size(2000, 500);
ChartArea area = new ChartArea();
chart.ChartAreas.Add(area);
chart.BackColor = System.Drawing.Color.Transparent;
chart.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart.ChartAreas[0].AxisX.Title = "sasdasdasd";
Series series = new Series()
{
Name = "series2",
IsVisibleInLegend = false,
ChartType = SeriesChartType.Column
};
chart.Series.Add(series);
foreach (CnbItem item in items)
{
DataPoint p1 = new DataPoint(0, Double.Parse(item.Kurz));
p1.Color = System.Drawing.Color.LightBlue;
p1.AxisLabel = item.Kod;
p1.LegendText = item.Kod;
p1.Label = item.Kurz;
series.Points.Add(p1);
}
string filename = "D:\\Chart.png";
chart.SaveImage(filename, ChartImageFormat.Png);
Update: Setting the the Chart's Backcolor to Transparent actually works just fine. However some image viewers do not display transparency; I use Irfanview as my default viewer and it is one of those which can't. I suspect yours also misses transparency..
Instead all transparency is rendered as black, so unless you have a non-black line color.. your axes and labels etc.. seem to be gone. Paint (on W10) is another one but renders transparency to white, so the black pixels are at least visible.
The below image is from Photoshop, which, of course, doesn't have that problem..

How to add right border of grid in Chart contol

Here is my code for setting properties of chart which is attached above:
chart2.ChartAreas[0].CursorX.IsUserEnabled = true;
chart2.ChartAreas[0].CursorX.IsUserSelectionEnabled = true;
chart2.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart2.ChartAreas[0].AxisX.Title = "t";
chart2.ChartAreas[0].AxisY.Title = "w(t)";
chart2.ChartAreas[0].AxisX.Minimum = classes[0].First();
chart2.ChartAreas[0].AxisX.Maximum = classes[m - 1].Last();
chart2.ChartAreas[0].AxisX.Interval = delta_t;
chart2.ChartAreas[0].AxisX.LabelStyle.Format = "{0:0.####}";
I need to add right border of grid so that it will be as it is shown below:
The right border is missing since your data don't nicely fit into the area.
There are many ways to fix this.
Here is the simplest one:
chart2.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart2.ChartAreas[0].AxisY2.LabelStyle.Enabled = false;
This adds a secondary Y-Axis and turns off its labels.
You can style it as needed:
chart2.ChartAreas[0].AxisY2.MajorTickMark.Enabled = false;
chart2.ChartAreas[0].AxisY2.LineWidth = 3;
You could also draw a line or add an annotation but this is by far the easiest solution.

Print FixedDocument onto label without PrintDialog (setting page margin and size myself)

tl;dr: Why do I need to set an extra "magic" offset on the left side when printing with WPF, XpsDocumentWriter and FixedDocument compared to printing with WinForms and PrintDocument?
I am building a WPF app that creates a FixedDocument and prints it to a label printer via XpsDocumentWriter. It's split in two parts, as I want the printer part to be able to receive and print a FixedDocument over the network from another app.
It's for use with a point of sale system, so I do not want to show a PrintDialog for every print. Size of labels and the printer name is stored in a template file. The things to be printed is in the template file combined with some data. (In below example printer name is taken from a combobox for now and just some demo things to be printed).
I retrieve the printer queue with the given printer name, and I can print to the printer, but the margins are quite off - the print is too far to the left, outside of the label and by more than just the liner margin (distance from label edge to the roll edge). By trial'n'error I found the magic offset to be around 20 plus the liner margin, but I guess that's different on another printer.
The old version of this app (which is made with WinForms and PrintDocument) prints allright (no matter how the printer properties' paper is setup). The wish from business is that all setup is in the template file, completely disregarding printer properties setup. That is how it is functioning now in the WinForms app.
What am I forgetting to set, what's the gotchas?
Should I do it some other way?
Do I need to set the PageMediaSize and PageMediaType, and why?
I'd like to do checks on PrinterCapabilities, but not if they depend on the current printer properties like the page size set in the properties. That one I'd like to set in code.
Update 11/3
I now tried printing to both a Metapace and a Zebra labelprinter, and both is happy with the 20 unit offset on the left side. But... why is it needed? When printing to pdf/xps, I get the offset to the left plus the margin on both sides. This I do not get with the old program in Winforms?
And do I need to do Measure, Arrange and UpdateLayout?
Part one - the FixedDocument creator
var printerName = CmbPrinters.SelectedValue.ToString();
var size =
(FlexTemplate.TemplateParser.TemplateFunctions.Size)
template.Functions.First(f => f is FlexTemplate.TemplateParser.TemplateFunctions.Size);
var labelSize = new Size(size.Width.Value, size.Height.Value);
// Dimensions are 1/96th of an inch, socalled Device Independent Pixels (matches 96 DPI, which is normal?)
var linerMargin = 4.7244094488189; // 1.25 mm
var magicOffset = 20; // 5.29 mm
// The document
var doc = new FixedDocument();
doc.PrintTicket = new PrintTicket();
var printTicket = (PrintTicket) doc.PrintTicket;
printTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.Unknown, size.Width.Value, size.Height.Value);
// New page
var page = new FixedPage
{
Width = labelSize.Width + magicOffset + 2 * linerMargin,
Height = labelSize.Height,
Margin = new Thickness(magicOffset + linerMargin, 0, linerMargin, 0)
};
// Page content
var border = new Border
{
Width = labelSize.Width,
Height = labelSize.Height,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(4)
};
FixedPage.SetLeft(border, 0);
FixedPage.SetTop(border, 0);
page.Children.Add(border);
// Next item on page
var tb = new TextBlock
{
Text = "Hello World!",
FontFamily = new FontFamily("Algerian Regular"),
FontSize = 30,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top
};
var content = new Border
{
Child = tb,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1)
};
FixedPage.SetLeft(content, 10);
FixedPage.SetTop(content, 10);
page.Children.Add(content);
// Next item on page
var tb2 = new TextBlock
{
Text = "SomethingElse",
FontFamily = new FontFamily("Segoe UI"),
FontSize = 20,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top
};
var content2 = new Border
{
Child = tb2,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1)
};
FixedPage.SetLeft(content2, 20);
FixedPage.SetTop(content2, 55);
page.Children.Add(content2);
//// Add the page to the document
//var pc = new PageContent(); // Old way of doing it (.NET 3.5 and earlier)
//((IAddChild)pc).AddChild(page); //
//doc.Pages.Add(pc); //
var pc = new PageContent();
pc.Child = page;
doc.Pages.Add(pc);
// Send it to the printer
FlexPrinter.Print(printerName, labelSize, doc);
Part two - the FixedDocument printer
// Get XpsDocumentWriter
PrintQueue queue = new PrintServer().GetPrintQueue(printerName);
var dw = PrintQueue.CreateXpsDocumentWriter(queue);
dw.Write(document);

Button image sides cropped

I'm trying to fit image to button perfectly.
But the image is cropped on its right and bottom faces, see attached print screen:
I edited the button as follows:
var l_oStopImage = Image.FromFile(#"C:\Users\AmitL\Downloads\Button-2-stop-icon72p.png");
var l_oStopPic = new Bitmap(l_oStopImage , new Size(btnStopOperation.Width, btnStopOperation.Height));
btnStopOperation.Image = l_oStopPic ;
btnStopOperation.ImageAlign = System.Drawing.ContentAlignment.MiddleCenter;
btnStopOperation.TabStop = false;
btnStopOperation.FlatStyle = FlatStyle.Flat;
btnStopOperation.FlatAppearance.BorderSize = 0;
I also tried to edit the BackgroundImageLayout but none of the ImageLayouts fixed the problem..
Any suggestions?
Thanks in advance
1https://msdn.microsoft.com/en-us/library/system.windows.forms.imagelayout(v=vs.110).aspx
You should use stretch, I suggest in designtime (this is not java where you have to add elements by code):
this.buttonOk.BackColor = System.Drawing.SystemColors.MenuHighlight;
this.buttonOk.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("buttonOk.BackgroundImage")));
this.buttonOk.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.buttonOk.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonOk.Location = new System.Drawing.Point(475, 15);
this.buttonOk.Name = "buttonOk";
this.buttonOk.Size = new System.Drawing.Size(50, 50);
this.buttonOk.TabIndex = 11;
this.buttonOk.UseVisualStyleBackColor = false;
this.buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
And it will work, done it many times before
I got this code from my own working Form1.Designer.cs but because of that: please use the Visual Studio designer and don't try to write all this code / logic in your constructor or something.
The problem is because you are showing an image with the same size as your button.
When you want an image fit in your button, the width and height of image should be at least 1 point less than your button size. (or in other word, you can set your button width and height 1 point more than the image size).
So you can change your code to this:
var l_oStopPic = new Bitmap(l_oStopImage ,
new Size(btnStopOperation.Width-1, btnStopOperation.Height-1));

XRLabel.Angle at Runtime

iam using DevExpress v.10.2 and want to show a XRLabel on XtraReport with Angle. If iam using the Designer it is working fine. But now i want to do this at runtime, because the Label.Text is dynamic. My Problem is that the Report doesnt show my Label. I read some DevExpress Support article, which descripe that it is just working on PDF-Format. But in my case i just see a small grey line.
I tried following to just populating my XRLabel for the first:
XRLabel druckinfo = new XRLabel();
druckinfo.Text = string.Format("SB{0} {1} EMAIL {2}", _Sachbearbeiter.Sbnr, _Kennung,
_Sachbearbeiter.Email1); //The values are filled and working.
druckinfo.Visible = true;
druckinfo.AutoWidth = false;
druckinfo.Angle = 90;
druckinfo.Font = new Font("Arial", 6f);
band.Controls.Add(druckinfo); //This is the DetailBand where i add other Labels too and its working fine.
druckinfo.HeightF = 500f; //Setting Height very high, because the text turns and i thought this is working. But seems to have no effect :(
druckinfo.LocationF = new PointF(400f, 400f);
druckinfo.Borders = DevExpress.XtraPrinting.BorderSide.All;
If i delete following line:
druckinfo.Angle = 90;
the Label becomes show fine but without Angle for sure.
Here a Screenshot which shows the Label with top settings on the PDF:
This are the settings of my Report:
_Report.PaperKind = PaperKind.A4;
_Report.ReportUnit = ReportUnit.HundredthsOfAnInch;
_Report.ShowPrintMarginsWarning = false;
_Report.Margins = new Margins(0, 0, 0, 0);
All other Properties are on default value. The Bands which exists are following:
PageHeaderBand
DetailBand
PageFooterBand
regards
This seems to be working :) I am not sure why this works and my top post dont. But i copied the code which is generated by designer and now it works.
XRLabel druckinfo = new XRLabel();
druckinfo.Angle = 90F;
druckinfo.Padding = new PaddingInfo(2, 2, 0, 0, 96F);
druckinfo.SizeF = new SizeF(29.16666F, 500F);
druckinfo.Font = new Font("Arial",8f);
druckinfo.Text = text;
_Band.Controls.Add(druckinfo);
druckinfo.LocationF = new PointF(0F, 500F);

Categories