I am familiar with Excel interop and have used it many times and most likely have become numb to the awkward ways in which interop works. Using PowerPoint interop can be very frustrating for numerous reasons, however, the biggest I feel is the lack of documentation and the differences between the different MS versions.
In addition, I looked for a third-party PowerPoint library and “Aspose” looked like the only option, unfortunately it is not a “free” option. I will assume there is a free third-party option and I just did not look in the right place… Or there may be a totally different way to do this possibly with XML. I am confident I am preaching to the choir.
Therefore, what I have been able to put together may work for you. For starters, looking at your current posted code, there is one part missing that you need to get the “copied” grid cells into the slide…
slide.Shapes.Paste();
This will paste the “copied” cells from the grid into an “unformatted” table into the slide. This will copy the “row header” if it is displayed in the grid in addition to the “new row” if the grids AllowUserToAddRows
is set to true
. If this “unformatted paste” works for you, then you are good to go.
If you prefer to have at least a minimally formatted table and ignore the row headers and last empty row… It may be easier to simply “create” a new Table
in the slide with the size we want along with the correct number of rows and columns. Granted, this may be more work, however, using the paste is going require this anyway “IF” you want the table formatted.
The method (below) takes a power point _Slide
and a DataGridView
. The code “creates” a new Table
in the slide based on the number of rows and columns in the given grid. With this approach, the table will be “formatted” using the default “Table Style” in the presentation. So, this may give you the formatting you want by simply “creating” the table as opposed to “pasting” the table.
I have tried to “apply” one of the existing “Table Styles” in power point, however, the examples I saw used something like…
table.ApplyStyle("{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}");
Which uses a GUID id to identify “which” style to use. I am not sure why MS decided on this GUID approach… this is beyond me, and it worked for “some” styles but not all.
Also, more common-sense solutions that showed something like…
table.StylePreset = TableStylePreset.MediumStyle2Accent2;
Unfortunately using my 2019 version of Office PowerPoint, this property does not exist. I have abandoned further research on this as it appears to be version dependent. Very annoying!
Given this, it may be easier if we format the cells individually as we want. We will need to add the cells text from the grid into the individual cells anyway, so we could also format the individual cells at the same time. Again, I am confident there is a better way, however, I could not find one.
Below the InsertTableIntoSlide(_Slide slide, DataGridView dgv)
method takes a slide and a grid as parameters. It will add a table to the slide with data from the given grid. A brief code trace is below.
First a check is made to get the number of total rows in the grid (not including the headers) totRows
. If the grids AllowUsersToAddRows
is true
, then the total rows variable is decremented by 1 to ignore this new row. Next the number of columns in the grid is set to the variable totCols
. The top left X and Y point is defined topLeftX
and topLeftY
to position the table in the slide along with the tables width
and height
.
ADDED NOTE: Using the AllowUserToAddRows
property to determine the number of rows … may NOT work as described above and will “miss” the last row… “IF” AllowUserToAddRows
is true
(default) AND the grid is data bound to a data source that does NOT allow new rows to be added. In that case you do NOT want to decrement the totRows
variable.
Next a “Table” “Shape” is added to the slide using the previous variables to define the base table dimensions. Next are two loops. The first loop adds the header cells to the first row in the table. Then a second loop to add the data from the cells in the grid… to the table cells in the slide.
The commented-out code is left as an example such that you want to do some specific formatting for the individual cells. This was not need in my case since the “default” table style was close to the formatting I wanted.
Also, a note that “ForeColor” is the “Back ground” color of the cell/shape. Strange!
I hope this helps and again, sympathize more about having to use PowerPoint interop… I could not.
private void InsertTableIntoSlide(_Slide slide, DataGridView dgv) {
try {
int totRows;
if (dgv.AllowUserToAddRows) {
totRows = dgv.Rows.Count - 1;
}
else {
totRows = dgv.Rows.Count;
}
int totCols = dgv.Columns.Count;
int topLeftX = 10;
int topLeftY = 10;
int width = 400;
int height = 100;
// add extra row for header row
Shape shape = slide.Shapes.AddTable(totRows + 1, totCols, topLeftX, topLeftY, width, height);
Table table = shape.Table;
for (int i = 0; i < dgv.Columns.Count; i++) {
table.Cell(1, i+1).Shape.TextFrame.TextRange.Text = dgv.Columns[i].HeaderText;
//table.Cell(1, i+1).Shape.Fill.ForeColor.RGB = ColorTranslator.ToOle(Color.Blue);
//table.Cell(1, i+1).Shape.TextFrame.TextRange.Font.Bold = Microsoft.Office.Core.MsoTriState.msoTrue;
//table.Cell(1, i+1).Shape.TextFrame.TextRange.Font.Color.RGB = ColorTranslator.ToOle(Color.White);
}
int curRow = 2;
for (int i = 0; i < totRows; i++) {
for (int j = 0; j < totCols; j++) {
if (dgv.Rows[i].Cells[j].Value != null) {
table.Cell(curRow, j + 1).Shape.TextFrame.TextRange.Text = dgv.Rows[i].Cells[j].Value.ToString();
//table.Cell(curRow, j + 1).Shape.Fill.ForeColor.RGB = ColorTranslator.ToOle(Color.LightGreen);
//table.Cell(curRow, j + 1).Shape.TextFrame.TextRange.Font.Bold = Microsoft.Office.Core.MsoTriState.msoTrue;
//table.Cell(curRow, j + 1).Shape.TextFrame.TextRange.Font.Color.RGB = ColorTranslator.ToOle(Color.Black);
}
}
curRow++;
}
}
catch (Exception ex) {
MessageBox.Show("Error: " + ex.Message);
}
}