| /* |
| * You may amend and distribute as you like, but don't remove this header! |
| * |
| * EPPlus provides server-side generation of Excel 2007 spreadsheets. |
| * See http://www.codeplex.com/EPPlus for details. |
| * |
| * All rights reserved. |
| * |
| * EPPlus is an Open Source project provided under the |
| * GNU General Public License (GPL) as published by the |
| * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| * The GNU General Public License can be viewed at http://www.opensource.org/licenses/gpl-license.php |
| * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html |
| * |
| * The code for this project may be used and redistributed by any means PROVIDING it is |
| * not sold for profit without the author's written consent, and providing that this notice |
| * and the author's name and all copyright notices remain intact. |
| * |
| * All code and executables are provided "as is" with no warranty either express or implied. |
| * The author accepts no liability for any damage or loss of business that this product may cause. |
| * |
| * Code change notes: |
| * |
| * Author Change Date |
| * ****************************************************************************** |
| * Jan Källman Added 2012-05-01 |
| *******************************************************************************/ |
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| using System.IO; |
| using OfficeOpenXml; |
| using System.Security.Cryptography.X509Certificates; |
| using System.Drawing; |
| using OfficeOpenXml.Style; |
| using OfficeOpenXml.Drawing.Chart; |
| namespace EPPlusSamples |
| { |
| class Sample15 |
| { |
| public static void VBASample(DirectoryInfo outputDir) |
| { |
| //Create a macro-enabled workbook from scratch. |
| VBASample1(outputDir); |
| |
| //Open Sample 1 and add code to change the chart to a bubble chart. |
| VBASample2(outputDir); |
| |
| //Simple battleships game from scratch. |
| VBASample3(outputDir); |
| } |
| private static void VBASample1(DirectoryInfo outputDir) |
| { |
| ExcelPackage pck = new ExcelPackage(); |
| |
| //Add a worksheet. |
| var ws=pck.Workbook.Worksheets.Add("VBA Sample"); |
| ws.Drawings.AddShape("VBASampleRect", eShapeStyle.RoundRect); |
| |
| //Create a vba project |
| pck.Workbook.CreateVBAProject(); |
| |
| //Now add some code to update the text of the shape... |
| var sb = new StringBuilder(); |
| |
| sb.AppendLine("Private Sub Workbook_Open()"); |
| sb.AppendLine(" [VBA Sample].Shapes(\"VBASampleRect\").TextEffect.Text = \"This text is set from VBA!\""); |
| sb.AppendLine("End Sub"); |
| pck.Workbook.CodeModule.Code = sb.ToString(); |
| |
| //And Save as xlsm |
| pck.SaveAs(new FileInfo(outputDir.FullName + @"\sample15-1.xlsm")); |
| } |
| private static void VBASample2(DirectoryInfo outputDir) |
| { |
| //Open Sample 1 again |
| ExcelPackage pck = new ExcelPackage(new FileInfo(outputDir.FullName + @"\sample1.xlsx")); |
| //Create a vba project |
| pck.Workbook.CreateVBAProject(); |
| |
| //Now add some code that creates a bubble chart... |
| var sb = new StringBuilder(); |
| |
| sb.AppendLine("Public Sub CreateBubbleChart()"); |
| sb.AppendLine("Dim co As ChartObject"); |
| sb.AppendLine("Set co = Inventory.ChartObjects.Add(10, 100, 400, 200)"); |
| sb.AppendLine("co.Chart.SetSourceData Source:=Range(\"'Inventory'!$B$1:$E$5\")"); |
| sb.AppendLine("co.Chart.ChartType = xlBubble3DEffect 'Add a bubblechart"); |
| sb.AppendLine("End Sub"); |
| |
| //Create a new module and set the code |
| var module = pck.Workbook.VbaProject.Modules.AddModule("EPPlusGeneratedCode"); |
| module.Code = sb.ToString(); |
| |
| //Call the newly created sub from the workbook open event |
| pck.Workbook.CodeModule.Code = "Private Sub Workbook_Open()\r\nCreateBubbleChart\r\nEnd Sub"; |
| |
| //Optionally, Sign the code with your company certificate. |
| /* |
| X509Store store = new X509Store(StoreLocation.CurrentUser); |
| store.Open(OpenFlags.ReadOnly); |
| pck.Workbook.VbaProject.Signature.Certificate = store.Certificates[0]; |
| */ |
| |
| //And Save as xlsm |
| pck.SaveAs(new FileInfo(outputDir.FullName + @"\sample15-2.xlsm")); |
| } |
| private static void VBASample3(DirectoryInfo outputDir) |
| { |
| //Now, lets do something a little bit more fun. |
| //We are going to create a simple battleships game from scratch. |
| |
| ExcelPackage pck = new ExcelPackage(); |
| |
| //Add a worksheet. |
| var ws = pck.Workbook.Worksheets.Add("Battleship"); |
| |
| ws.View.ShowGridLines = false; |
| ws.View.ShowHeaders = false; |
| |
| ws.DefaultColWidth = 3; |
| ws.DefaultRowHeight = 15; |
| |
| int gridSize=10; |
| |
| //Create the boards |
| var board1 = ws.Cells[2, 2, 2 + gridSize - 1, 2 + gridSize - 1]; |
| var board2 = ws.Cells[2, 4+gridSize-1, 2 + gridSize-1, 4 + (gridSize-1)*2]; |
| CreateBoard(board1); |
| CreateBoard(board2); |
| ws.Select("B2"); |
| ws.Protection.IsProtected = true; |
| ws.Protection.AllowSelectLockedCells = true; |
| |
| //Create the VBA Project |
| pck.Workbook.CreateVBAProject(); |
| //Password protect your code |
| pck.Workbook.VbaProject.Protection.SetPassword("EPPlus"); |
| |
| //Add all the code from the textfiles in the Vba-Code sub-folder. |
| pck.Workbook.CodeModule.Code = File.ReadAllText("..\\..\\VBA-Code\\ThisWorkbook.txt"); |
| |
| //Add the sheet code |
| ws.CodeModule.Code = File.ReadAllText("..\\..\\VBA-Code\\BattleshipSheet.txt"); |
| var m1=pck.Workbook.VbaProject.Modules.AddModule("Code"); |
| string code = File.ReadAllText("..\\..\\VBA-Code\\CodeModule.txt"); |
| |
| //Insert your ships on the right board. you can changes these, but don't cheat ;) |
| var ships = new string[]{ |
| "N3:N7", |
| "P2:S2", |
| "V9:V11", |
| "O10:Q10", |
| "R11:S11"}; |
| |
| //Note: For security reasons you should never mix external data and code(to avoid code injections!), especially not on a webserver. |
| //If you deside to do that anyway, be very careful with the validation of the data. |
| //Be extra carefull if you sign the code. |
| //Read more here http://en.wikipedia.org/wiki/Code_injection |
| |
| code = string.Format(code, ships[0],ships[1],ships[2],ships[3],ships[4], board1.Address, board2.Address); //Ships are injected into the constants in the module |
| m1.Code = code; |
| |
| //Ships are displayed with a black background |
| string shipsaddress = string.Join(",", ships); |
| ws.Cells[shipsaddress].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid; |
| ws.Cells[shipsaddress].Style.Fill.BackgroundColor.SetColor(Color.Black); |
| |
| var m2 = pck.Workbook.VbaProject.Modules.AddModule("ComputerPlay"); |
| m2.Code = File.ReadAllText("..\\..\\VBA-Code\\ComputerPlayModule.txt"); |
| |
| var c1 = pck.Workbook.VbaProject.Modules.AddClass("Ship",false); |
| c1.Code = File.ReadAllText("..\\..\\VBA-Code\\ShipClass.txt"); |
| |
| //Add the info text shape. |
| var tb = ws.Drawings.AddShape("txtInfo", eShapeStyle.Rect); |
| tb.SetPosition(1, 0, 27, 0); |
| tb.Fill.Color = Color.LightSlateGray; |
| var rt1 = tb.RichText.Add("Battleships"); |
| rt1.Bold = true; |
| tb.RichText.Add("\r\nDouble-click on the left board to make your move. Find and sink all ships to win!"); |
| |
| //Set the headers. |
| ws.SetValue("B1", "Computer Grid"); |
| ws.SetValue("M1", "Your Grid"); |
| ws.Row(1).Style.Font.Size = 18; |
| |
| AddChart(ws.Cells["B13"], "chtHitPercent", "Player"); |
| AddChart(ws.Cells["M13"], "chtComputerHitPercent", "Computer"); |
| |
| ws.Names.Add("LogStart", ws.Cells["B24"]); |
| ws.Cells["B24:X224"].Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.Black); |
| ws.Cells["B25:X224"].Style.Font.Name = "Consolas"; |
| ws.SetValue("B24", "Log"); |
| ws.Cells["B24"].Style.Font.Bold = true; |
| ws.Cells["B24:X24"].Style.Border.BorderAround(ExcelBorderStyle.Thin, Color.Black); |
| var cf=ws.Cells["B25:B224"].ConditionalFormatting.AddContainsText(); |
| cf.Text = "hit"; |
| cf.Style.Font.Color.Color = Color.Red; |
| |
| //If you have a valid certificate for code signing you can use this code to set it. |
| ///*** Try to find a cert valid for signing... ***/ |
| //X509Store store = new X509Store(StoreLocation.CurrentUser); |
| //store.Open(OpenFlags.ReadOnly); |
| //foreach (var cert in store.Certificates) |
| //{ |
| // if (cert.HasPrivateKey && cert.NotBefore <= DateTime.Today && cert.NotAfter >= DateTime.Today) |
| // { |
| // pck.Workbook.VbaProject.Signature.Certificate = cert; |
| // break; |
| // } |
| //} |
| |
| pck.SaveAs(new FileInfo(outputDir.FullName + @"\sample15-3.xlsm")); |
| } |
| |
| private static void AddChart(ExcelRange rng,string name, string prefix) |
| { |
| var chrt = (ExcelPieChart)rng.Worksheet.Drawings.AddChart(name, eChartType.Pie); |
| chrt.SetPosition(rng.Start.Row-1, 0, rng.Start.Column-1, 0); |
| chrt.To.Row = rng.Start.Row+9; |
| chrt.To.Column = rng.Start.Column + 9; |
| chrt.Style = eChartStyle.Style18; |
| chrt.DataLabel.ShowPercent = true; |
| |
| var serie = chrt.Series.Add(rng.Offset(2, 2, 1, 2), rng.Offset(1, 2, 1, 2)); |
| serie.Header = "Hits"; |
| |
| chrt.Title.Text = "Hit ratio"; |
| |
| var n1 = rng.Worksheet.Names.Add(prefix + "Misses", rng.Offset(2, 2)); |
| n1.Value = 0; |
| var n2 = rng.Worksheet.Names.Add(prefix + "Hits", rng.Offset(2, 3)); |
| n2.Value = 0; |
| rng.Offset(1, 2).Value = "Misses"; |
| rng.Offset(1, 3).Value = "Hits"; |
| } |
| |
| private static void CreateBoard(ExcelRange rng) |
| { |
| //Create a gradiant background with one dark and one light blue color |
| rng.Style.Fill.Gradient.Color1.SetColor(Color.FromArgb(0x80, 0x80, 0XFF)); |
| rng.Style.Fill.Gradient.Color2.SetColor(Color.FromArgb(0x20, 0x20, 0XFF)); |
| rng.Style.Fill.Gradient.Type = ExcelFillGradientType.None; |
| for (int col = 0; col <= rng.End.Column - rng.Start.Column; col++) |
| { |
| for (int row = 0; row <= rng.End.Row - rng.Start.Row; row++) |
| { |
| if (col % 4 == 0) |
| { |
| rng.Offset(row, col, 1, 1).Style.Fill.Gradient.Degree = 45; |
| } |
| if (col % 4 == 1) |
| { |
| rng.Offset(row, col, 1, 1).Style.Fill.Gradient.Degree = 70; |
| } |
| if (col % 4 == 2) |
| { |
| rng.Offset(row, col, 1, 1).Style.Fill.Gradient.Degree = 110; |
| } |
| else |
| { |
| rng.Offset(row, col, 1, 1).Style.Fill.Gradient.Degree = 135; |
| } |
| } |
| } |
| //Set the inner cell border to thin, light gray |
| rng.Style.Border.Top.Style = ExcelBorderStyle.Thin; |
| rng.Style.Border.Top.Color.SetColor(Color.Gray); |
| rng.Style.Border.Right.Style = ExcelBorderStyle.Thin; |
| rng.Style.Border.Right.Color.SetColor(Color.Gray); |
| rng.Style.Border.Left.Style = ExcelBorderStyle.Thin; |
| rng.Style.Border.Left.Color.SetColor(Color.Gray); |
| rng.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; |
| rng.Style.Border.Bottom.Color.SetColor(Color.Gray); |
| |
| //Solid black border around the board. |
| rng.Style.Border.BorderAround(ExcelBorderStyle.Medium, Color.Black); |
| } |
| } |
| } |