|  | /* | 
|  | * 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); | 
|  | } | 
|  | } | 
|  | } |