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