├── Source ├── CrystalReportsNinja │ ├── Export.ico │ ├── Program.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ ├── app.manifest │ │ ├── Settings.settings │ │ ├── Resources.resx │ │ └── Settings.Designer.cs │ ├── LogWriter.cs │ ├── App.config │ ├── CrystalReportsNinja.csproj │ ├── ParameterCore.cs │ ├── Helper.cs │ ├── ArgumentContainer.cs │ └── ReportProcessor.cs └── CrystalReportsNinja.sln ├── Testing └── AdventureWorksLt │ ├── CrystalReport_Test1.rpt │ ├── CrystalReport_Test2.rpt │ ├── CrystalReport_Test2 Arguments.txt │ ├── CrystalReport_Test1 Arguments.txt │ ├── uspCrystalReport_Test1.sql │ ├── uspCrystalReport_Test2.sql │ ├── uspCrystalReport_Test2A.sql │ └── Readme.txt ├── .github └── FUNDING.yml ├── .gitattributes ├── .gitignore └── README.md /Source/CrystalReportsNinja/Export.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhertzfeld/CrystalReportsNinja/HEAD/Source/CrystalReportsNinja/Export.ico -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/CrystalReport_Test1.rpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhertzfeld/CrystalReportsNinja/HEAD/Testing/AdventureWorksLt/CrystalReport_Test1.rpt -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/CrystalReport_Test2.rpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mhertzfeld/CrystalReportsNinja/HEAD/Testing/AdventureWorksLt/CrystalReport_Test2.rpt -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/CrystalReport_Test2 Arguments.txt: -------------------------------------------------------------------------------- 1 | -u myuser -p mypassword -s mydb.database.windows.net -d AdventureWorksLT -f CrystalReport_Test2.rpt -o test2.pdf -a "@Size:L" -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/CrystalReport_Test1 Arguments.txt: -------------------------------------------------------------------------------- 1 | -u useraccount -p password -f c:\tmp\CrystalReport_Test1.rpt -o c:\tmp\test1.pdf -e pdf -sf {uspCrystalReport_Test1;1.ListPrice}=9.50 -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/uspCrystalReport_Test1.sql: -------------------------------------------------------------------------------- 1 | /****** Object: StoredProcedure [dbo].[uspCrystalReport_Test1] Script Date: 9/3/2020 5:20:45 PM ******/ 2 | SET ANSI_NULLS ON 3 | GO 4 | 5 | SET QUOTED_IDENTIFIER ON 6 | GO 7 | 8 | CREATE PROCEDURE [dbo].[uspCrystalReport_Test1] 9 | 10 | as 11 | 12 | select * from saleslt.Product 13 | GO 14 | 15 | -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/uspCrystalReport_Test2.sql: -------------------------------------------------------------------------------- 1 | /****** Object: StoredProcedure [dbo].[uspCrystalReport_Test2] Script Date: 9/4/2020 11:45:06 AM ******/ 2 | SET ANSI_NULLS ON 3 | GO 4 | 5 | SET QUOTED_IDENTIFIER ON 6 | GO 7 | 8 | create procedure [dbo].[uspCrystalReport_Test2] 9 | 10 | @Size nvarchar(5) 11 | 12 | as 13 | 14 | select * from SalesLT.Product where size = @Size; 15 | GO 16 | 17 | -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/uspCrystalReport_Test2A.sql: -------------------------------------------------------------------------------- 1 | /****** Object: StoredProcedure [dbo].[uspCrystalReport_Test2A] Script Date: 9/4/2020 11:51:28 AM ******/ 2 | SET ANSI_NULLS ON 3 | GO 4 | 5 | SET QUOTED_IDENTIFIER ON 6 | GO 7 | 8 | create procedure [dbo].[uspCrystalReport_Test2A] 9 | 10 | @Size nvarchar(5) 11 | 12 | as 13 | 14 | select * from SalesLT.Product where size != @Size; 15 | GO 16 | 17 | -------------------------------------------------------------------------------- /Testing/AdventureWorksLt/Readme.txt: -------------------------------------------------------------------------------- 1 | Uses Adventure Works Database. 2 | https://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks 3 | 4 | 5 | 6 | CrystalReport_Test1 7 | You must create and grant access to the uspCrystalReport_Test1 stored procedure. 8 | 9 | 10 | 11 | CrystalReport_Test2 12 | You must create and grant access to the uspCrystalReport_Test2 and uspCrystalReport_Test2A stored procedures. -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [mhertzfeld] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CrystalReportsNinja 4 | { 5 | public class Program 6 | { 7 | static int Main(string[] args) 8 | { 9 | try 10 | { 11 | // read program arguments into Argument Container 12 | ArgumentContainer argContainer = new ArgumentContainer(); 13 | argContainer.ReadArguments(args); 14 | 15 | if (argContainer.GetHelp) 16 | Helper.ShowHelpMessage(); 17 | else 18 | { 19 | string _logFilename = string.Empty; 20 | 21 | if (argContainer.EnableLog) 22 | argContainer.LogFileName = "ninja-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".log"; 23 | 24 | ReportProcessor reportNinja = new ReportProcessor(); 25 | reportNinja.ReportArguments = argContainer; 26 | reportNinja.Run(); 27 | } 28 | } 29 | catch (Exception ex) 30 | { 31 | Console.WriteLine(string.Format("Exception: {0}",ex.Message)); 32 | Console.WriteLine(string.Format("Inner Exception: {0}", ex.InnerException)); 33 | 34 | return 1; 35 | } 36 | 37 | return 0; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Crystal Reports Ninja")] 9 | [assembly: AssemblyDescription("Forked from https://github.com/rainforestnet/CrystalReportsNinja")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Matthew Hertzfeld")] 12 | [assembly: AssemblyProduct("https://github.com/mhertzfeld/CrystalReportsNinja")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a9bc6ccb-afd4-4b80-bde0-dbc99c8d51c2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.11.0.1")] 36 | [assembly: AssemblyFileVersion("1.11.0.1")] -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/LogWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Diagnostics; 4 | 5 | namespace CrystalReportsNinja 6 | { 7 | public class LogWriter 8 | { 9 | private static string _progDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\"; 10 | private static string _logFilename; 11 | private static Boolean _LogToConsole; 12 | 13 | public LogWriter(string filename, Boolean logToConsole) 14 | { 15 | _logFilename = filename; 16 | 17 | _LogToConsole = logToConsole; 18 | } 19 | 20 | public void Write(string text) 21 | { 22 | Trace.WriteLine(string.Format("{0}\t{1}\t{2}", DateTime.Now.ToString("dd-MM-yyyy"), DateTime.Now.ToString("HH:mm:ss"), text)); 23 | 24 | if (_logFilename.Length > 0) 25 | { 26 | StreamWriter writer; 27 | 28 | if (!File.Exists(_progDir + _logFilename)) 29 | writer = File.CreateText(_progDir + _logFilename); 30 | else 31 | writer = File.AppendText(_progDir + _logFilename); 32 | 33 | string date, time; 34 | date = DateTime.Now.ToString("dd-MM-yyyy"); 35 | time = DateTime.Now.ToString("HH:mm:ss"); 36 | 37 | writer.WriteLine(string.Format("{0}\t{1}\t{2}", date, time, text)); 38 | writer.Close(); 39 | writer.Dispose(); 40 | } 41 | 42 | if (_LogToConsole) 43 | { 44 | Console.WriteLine(string.Format("{0}\t{1}\t{2}", DateTime.Now.ToString("dd-MM-yyyy"), DateTime.Now.ToString("HH:mm:ss"), text)); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.16 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrystalReportsNinja", "CrystalReportsNinja\CrystalReportsNinja.csproj", "{A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|x64.ActiveCfg = Debug|x64 21 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|x64.Build.0 = Debug|x64 22 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|x86.ActiveCfg = Debug|x86 23 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Debug|x86.Build.0 = Debug|x86 24 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|x64.ActiveCfg = Release|x64 27 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|x64.Build.0 = Release|x64 28 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|x86.ActiveCfg = Release|x86 29 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2}.Release|x86.Build.0 = Release|x86 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {44A09627-FDAE-477B-AFEF-226B3839C816} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CrystalReportsNinja.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CrystalReportsNinja.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 55 | 56 | 70 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | False 7 | 8 | 9 | True 10 | 11 | 12 | Smtp.office365.com 13 | 14 | 15 | 587 16 | 17 | 18 | True 19 | 20 | 21 | True 22 | 23 | 24 | NA 25 | 26 | 27 | NA 28 | 29 | 30 | The information contained is intended for the named recipients only, it may contain confidential and/or legally privileged information and is only intended for the use of the person to whom it is addressed. If you have received this e-mail in error you must not copy, duplicate, forward, print or distribute any information contained herein, but must ensure that this e-mail is permanently deleted and advise the sender. 31 | 32 | 33 | True 34 | 35 | 36 | 37 | 38 | 39 | SQLSERVERNAME 40 | 41 | 42 | SQLDBNAME 43 | 44 | 45 | REPORTUSERNAME 46 | 47 | 48 | REPORTUSERPASSWORD 49 | 50 | 51 | USERNAME 52 | 53 | 54 | PASSWORD 55 | 56 | 57 | noreply@noreply.com 58 | 59 | 60 | NoReply 61 | 62 | 63 | Automated Crystal Reports 64 | 65 | 66 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | False 15 | 16 | 17 | True 18 | 19 | 20 | Smtp.office365.com 21 | 22 | 23 | 587 24 | 25 | 26 | True 27 | 28 | 29 | True 30 | 31 | 32 | NA 33 | 34 | 35 | NA 36 | 37 | 38 | The information contained is intended for the named recipients only, it may contain confidential and/or legally privileged information and is only intended for the use of the person to whom it is addressed. If you have received this e-mail in error you must not copy, duplicate, forward, print or distribute any information contained herein, but must ensure that this e-mail is permanently deleted and advise the sender. 39 | 40 | 41 | True 42 | 43 | 44 | 45 | 46 | 47 | SQLSERVERNAME 48 | 49 | 50 | SQLDBNAME 51 | 52 | 53 | REPORTUSERNAME 54 | 55 | 56 | REPORTUSERPASSWORD 57 | 58 | 59 | USERNAME 60 | 61 | 62 | PASSWORD 63 | 64 | 65 | noreply@noreply.com 66 | 67 | 68 | NoReply 69 | 70 | 71 | Automated Crystal Reports 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | text/microsoft-resx 91 | 92 | 93 | 1.3 94 | 95 | 96 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 97 | 98 | 99 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 100 | 101 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/CrystalReportsNinja.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A9BC6CCB-AFD4-4B80-BDE0-DBC99C8D51C2} 8 | Exe 9 | CrystalReportsNinja 10 | CrystalReportsNinja 11 | v4.7.2 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | false 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | true 39 | bin\x64\Debug\ 40 | DEBUG;TRACE 41 | full 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | 46 | 47 | bin\x64\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x64 52 | prompt 53 | MinimumRecommendedRules.ruleset 54 | 55 | 56 | true 57 | bin\x86\Debug\ 58 | DEBUG;TRACE 59 | full 60 | x86 61 | prompt 62 | MinimumRecommendedRules.ruleset 63 | 64 | 65 | bin\x86\Release\ 66 | TRACE 67 | true 68 | pdbonly 69 | x86 70 | prompt 71 | MinimumRecommendedRules.ruleset 72 | 73 | 74 | Export.ico 75 | 76 | 77 | Properties\app.manifest 78 | 79 | 80 | 81 | False 82 | 83 | 84 | False 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | True 96 | True 97 | Settings.settings 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | SettingsSingleFileGenerator 110 | Settings.Designer.cs 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/ParameterCore.cs: -------------------------------------------------------------------------------- 1 | using CrystalDecisions.CrystalReports.Engine; 2 | using CrystalDecisions.Shared; 3 | using System.Collections.Generic; 4 | 5 | namespace CrystalReportsNinja 6 | { 7 | internal class UserParameter 8 | { 9 | public string ParameterName { get; set; } 10 | public string ParameterValue { get; set; } 11 | } 12 | 13 | public class ParameterCore 14 | { 15 | private List _userParams; 16 | private LogWriter _logger; 17 | private List _parameterCollection; 18 | 19 | public ParameterCore(string logfilename, ArgumentContainer _ArgumentContainer) 20 | { 21 | _userParams = new List(); 22 | _parameterCollection = _ArgumentContainer.ParameterCollection; 23 | _logger = new LogWriter(logfilename, _ArgumentContainer.EnableLogToConsole); 24 | } 25 | 26 | public void ProcessRawParameters() 27 | { 28 | foreach (string input in _parameterCollection) 29 | { 30 | _userParams.Add(new UserParameter 31 | { 32 | ParameterName = input.Substring(0, input.IndexOf(":")), 33 | ParameterValue = (input.Substring(input.IndexOf(":") + 1, input.Length - (input.IndexOf(":") + 1))) 34 | } 35 | ); 36 | } 37 | _logger.Write(string.Format("Number of Parameters passed by the users script = {0}", _userParams.Count)); 38 | } 39 | 40 | /// 41 | /// A report can contains more than One parameters, hence 42 | /// we loop through all parameters that user has input and match 43 | /// it with parameter definition of Crystal Reports file. 44 | /// 45 | public ParameterValues GetParameterValues(ParameterFieldDefinition ParameterDef) 46 | { 47 | ParameterValues paramValues = new ParameterValues(); 48 | //ParameterValue paramValue; 49 | 50 | for (int j = 0; j < _userParams.Count; j++) 51 | { 52 | if (ParameterDef.Name == _userParams[j].ParameterName) 53 | { 54 | if (ParameterDef.EnableAllowMultipleValue && _userParams[j].ParameterValue.IndexOf("|") != -1) 55 | { 56 | // multiple value parameter 57 | List values = new List(); 58 | values = Helper.SplitIntoSingleValue(_userParams[j].ParameterValue); //split multiple value into single value regardless discrete or range 59 | 60 | for (int k = 0; k < values.Count; k++) 61 | { 62 | ParameterValue paramValue = GetSingleParamValue(ParameterDef.DiscreteOrRangeKind, values[k], ParameterDef.Name); 63 | paramValues.Add(paramValue); 64 | _logger.Write(string.Format("Multiple Value Parameter - Prompt = {0} - {1} = {2}", ParameterDef.PromptText, ParameterDef.Name, _userParams[j].ParameterValue)); 65 | } 66 | } 67 | else 68 | { 69 | // simple single value parameter 70 | ParameterValue paramValue = GetSingleParamValue(ParameterDef.DiscreteOrRangeKind, _userParams[j].ParameterValue, ParameterDef.Name); 71 | paramValues.Add(paramValue); 72 | _logger.Write(string.Format("Single Value Parameter - Prompt = {0} - {1} = {2}", ParameterDef.PromptText, _userParams[j].ParameterName, _userParams[j].ParameterValue)); 73 | } 74 | 75 | } 76 | } 77 | return paramValues; 78 | } 79 | 80 | /// 81 | /// Extract value from a raw parameter string. 82 | /// "paraInputText" must be just a single value and not a multiple value parameters 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | /// Complex parameter input can be as such, 89 | /// pipe "|" is used to split multiple values, comma "," is used to split Start and End value of a range. 90 | /// 91 | /// -a "date:(01-01-2001,28-02-2001)|(02-01-2002,31-10-2002)|(02-08-2002,31-12-2002)" 92 | /// -a "Client:(Ace Soft Inc,Best Computer Inc)|(Xtreme Bike Inc,Zebra Design Inc)" 93 | /// 94 | /// 95 | private ParameterValue GetSingleParamValue(DiscreteOrRangeKind paraType, string paraInputText, string paraName) 96 | { 97 | ParameterValues paraValues = new ParameterValues(); 98 | bool isDiscreateType = paraType == DiscreteOrRangeKind.DiscreteValue ? true : false; 99 | bool isDiscreateAndRangeType = paraType == DiscreteOrRangeKind.DiscreteAndRangeValue ? true : false; 100 | bool isRangeType = paraType == DiscreteOrRangeKind.RangeValue ? true : false; 101 | bool paraTextIsRange = paraInputText.IndexOf("(") != -1 ? true : false; 102 | 103 | if (isDiscreateType || (isDiscreateAndRangeType && !paraTextIsRange)) 104 | { 105 | var paraValue = new ParameterDiscreteValue() 106 | { 107 | Value = paraInputText 108 | }; 109 | _logger.Write(string.Format("Discrete Parameter : {0} = {1}", paraName, ((ParameterDiscreteValue)paraValue).Value)); 110 | return paraValue; 111 | } 112 | else if (isRangeType || (isDiscreateAndRangeType && paraTextIsRange)) 113 | { 114 | // sample of range parameter (01-01-2001,28-02-2001) 115 | var paraValue = new ParameterRangeValue() 116 | { 117 | StartValue = Helper.GetStartValue(paraInputText), 118 | EndValue = Helper.GetEndValue(paraInputText) 119 | }; 120 | _logger.Write(string.Format("Range Parameter : {0} = {1} to {2} ", paraName, ((ParameterRangeValue)paraValue).StartValue, ((ParameterRangeValue)paraValue).EndValue)); 121 | return paraValue; 122 | } 123 | return null; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Helper.cs: -------------------------------------------------------------------------------- 1 | using CrystalDecisions.Shared; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace CrystalReportsNinja 7 | { 8 | public static class Helper 9 | { 10 | /// 11 | /// Display help message 12 | /// 13 | /// 14 | public static void ShowHelpMessage() 15 | { 16 | Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; 17 | 18 | Console.WriteLine("\nCrystal Reports Ninja. Version {0}", v.ToString()); 19 | Console.WriteLine("Copyright(c) 2017 Rainforest Software Solution http://www.rainforestnet.com"); 20 | Console.WriteLine("CrystalReportsNinja Arguments Listing"); 21 | Console.WriteLine("\n -------------- DB and Report Config --------------"); 22 | Console.WriteLine(" -I Use Intergrated Security for DB Access. (Optional, False by Default"); 23 | Console.WriteLine(" -U database login username. (Optional, If not set IntegratedSecurity is used"); 24 | Console.WriteLine(" -P database login password. (Optional, If not set IntegratedSecurity is used"); 25 | Console.WriteLine(" -F Crystal reports path and filename. (Mandatory)"); 26 | Console.WriteLine(" -S Database Server Name. (instance name)"); 27 | Console.WriteLine(" -D Database Name."); 28 | Console.WriteLine(" -SF Selection Formula."); 29 | Console.WriteLine("\n ------------------ Output Config -----------------"); 30 | Console.WriteLine(" -O Output path and filename."); 31 | Console.WriteLine(" -E Export file type. (pdf,doc,xls,xlsx,rtf,htm,rpt,txt,csv...) If print to printer simply specify \"print\""); 32 | Console.WriteLine(" -a Parameter value."); 33 | Console.WriteLine(" -N Printer Name. (Set to DFLT to use inbuilt report printer, If not set the Windows Default Printer will be used, Network printer : \\\\PrintServer\\Printername or Local printer : printername)"); 34 | Console.WriteLine(" -C Number of copy to be printed."); 35 | Console.WriteLine("\n ----------------- Logging Config -----------------"); 36 | Console.WriteLine(" -L To write a log file. filename ninja-yyyyMMddHHmmss.log"); 37 | Console.WriteLine(" -LC To write log output to console"); 38 | Console.WriteLine("\n ------------------ Email Config ------------------"); 39 | Console.WriteLine(" -M Email Report Output. (Enable Email Support)"); 40 | Console.WriteLine(" -MF Email Address to SEND From. (Optional, Default: noreply@noreply.com)"); 41 | Console.WriteLine(" -MN Email Address to SEND From Display Name. (Optional, Default: Crystal Reports)"); 42 | Console.WriteLine(" -MT Email Address to SEND To. (Mandatory)"); 43 | Console.WriteLine(" -MC Email Address to be CC'd. (Optional)"); 44 | Console.WriteLine(" -MB Email Address to be BCC'd. (Optional)"); 45 | Console.WriteLine(" -MS Email Subject Line of the Email. (Optional, Default: Crystal Reports)"); 46 | Console.WriteLine(" -MI Email Message Body. (Optional, Default: Blank)"); 47 | Console.WriteLine(" -MK Email Keep Output File after sending. (Optional, Default: False)"); 48 | Console.WriteLine(" -MSA SMTP server address. (Mandatory, if SSL enabled FQDN is required)"); 49 | Console.WriteLine(" -MSP SMTP server port. (Optional, Default: 25)"); 50 | Console.WriteLine(" -MSE SMTP server Enable SSL. (Optional, Default: False"); 51 | Console.WriteLine(" -MSC SMTP Auth - Use Current User Credentials, (Optional, Default: False "); 52 | Console.WriteLine(" -MUN SMTP server Username. (Optional) \"domain\\username\""); 53 | Console.WriteLine(" -MPW SMTP server Password. (Optional) \"password\""); 54 | Console.WriteLine(" ----- SMTP Auth Note: If Username and Password is provided, -MSC Param is ignored and specifed Credentials are used to send email -----"); 55 | Console.WriteLine(" ----- SMTP Auth Note: If -MSC + -MUN + -MPW Params are not set, Email is sent using Anonymous User -----"); 56 | Console.WriteLine(" ----- SMTP Auth Note: If -MSC is set and -MUN + -MPW are not, Email is sent using Current User Credentials -----"); 57 | Console.WriteLine("\n ----------------- Example Scripts ----------------"); 58 | Console.WriteLine(" Example: C:\\> CrystalReportsNinja -U user1 -P mypass -S Server01 -D \"ExtremeDB\" -F c:\\test.rpt -O d:\\test.pdf -a \"Supplier Name:Active Outdoors\" -a \"Date Range:(12-01-2001,12-04-2002)\""); 59 | Console.WriteLine(" Example Email : Add this to the above line, -M -MSA SMTP-FQDN -MSP 25 -MUN \"smtpUN\" -MPW \"smtpPW\" -MN \"Report User\" -MF noreply@noreply.com.au -MS \"Report Subject\" -MI \"Report Body\" -MN \"Report User\" -MF noreply@noreply.com.au -MT myemail@domain.com"); 60 | Console.WriteLine("\n Learn more in https://github.com/mhertzfeld/CrystalReportsNinja"); 61 | 62 | } 63 | 64 | /// 65 | /// Get Start Value of Range parameter 66 | /// 67 | /// 68 | /// 69 | public static string GetStartValue(string parameterString) 70 | { 71 | int delimiter = parameterString.IndexOf(","); 72 | int leftbracket = parameterString.IndexOf("("); 73 | 74 | if (delimiter == -1 || leftbracket == -1) 75 | throw new Exception("Invalid Range Parameter value. eg. -a \"parameter name:(1000,2000)\""); 76 | 77 | return parameterString.Substring(leftbracket + 1, delimiter - 1).Trim(); 78 | } 79 | 80 | /// 81 | /// Get End Value of a range parameter 82 | /// 83 | /// 84 | /// 85 | public static string GetEndValue(string parameterString) 86 | { 87 | int delimiter = parameterString.IndexOf(","); 88 | int rightbracket = parameterString.IndexOf(")"); 89 | 90 | if (delimiter == -1 || rightbracket == -1) 91 | throw new Exception("Invalid Range Parameter value. eg. -a \"parameter name:(1000,2000)\""); 92 | 93 | return parameterString.Substring(delimiter + 1, rightbracket - delimiter - 1).Trim(); 94 | } 95 | 96 | /// 97 | /// Split multiple value parameter example "100|22|222" to 3 string in List 98 | /// 99 | /// 100 | /// 101 | public static List SplitIntoSingleValue(string multipleValueString) 102 | { 103 | //if "|" found,means multiple values parameter found 104 | int pipeStartIndex = 0; 105 | List singleValue = new List(); 106 | bool loop = true; //loop false when it reaches the last parameter to read 107 | 108 | //pipeIndex is start search position of parameter string 109 | while (loop) 110 | { 111 | if (pipeStartIndex == multipleValueString.LastIndexOf("|") + 1) 112 | loop = false; 113 | 114 | if (loop) //if this is not the last parameter 115 | singleValue.Add(multipleValueString.Substring(pipeStartIndex, multipleValueString.IndexOf("|", pipeStartIndex + 1) - pipeStartIndex).Trim()); 116 | else 117 | singleValue.Add(multipleValueString.Substring(pipeStartIndex, multipleValueString.Length - pipeStartIndex).Trim()); 118 | 119 | pipeStartIndex = multipleValueString.IndexOf("|", pipeStartIndex) + 1; //index to the next search of pipe 120 | } 121 | return singleValue; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CrystalReportsNinja.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 29 | public bool SQL_Use_IntegratedSecurity { 30 | get { 31 | return ((bool)(this["SQL_Use_IntegratedSecurity"])); 32 | } 33 | set { 34 | this["SQL_Use_IntegratedSecurity"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 41 | public bool EnableLogToConsole { 42 | get { 43 | return ((bool)(this["EnableLogToConsole"])); 44 | } 45 | set { 46 | this["EnableLogToConsole"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("Smtp.office365.com")] 53 | public string SMTP_Server_Address { 54 | get { 55 | return ((string)(this["SMTP_Server_Address"])); 56 | } 57 | set { 58 | this["SMTP_Server_Address"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("587")] 65 | public int SMTP_Server_Port { 66 | get { 67 | return ((int)(this["SMTP_Server_Port"])); 68 | } 69 | set { 70 | this["SMTP_Server_Port"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 77 | public bool SMTP_SSL_Reqruired { 78 | get { 79 | return ((bool)(this["SMTP_SSL_Reqruired"])); 80 | } 81 | set { 82 | this["SMTP_SSL_Reqruired"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 89 | public bool SMTP_Authentication_Used { 90 | get { 91 | return ((bool)(this["SMTP_Authentication_Used"])); 92 | } 93 | set { 94 | this["SMTP_Authentication_Used"] = value; 95 | } 96 | } 97 | 98 | [global::System.Configuration.UserScopedSettingAttribute()] 99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 100 | [global::System.Configuration.DefaultSettingValueAttribute("NA")] 101 | public string Email_CC { 102 | get { 103 | return ((string)(this["Email_CC"])); 104 | } 105 | set { 106 | this["Email_CC"] = value; 107 | } 108 | } 109 | 110 | [global::System.Configuration.UserScopedSettingAttribute()] 111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 112 | [global::System.Configuration.DefaultSettingValueAttribute("NA")] 113 | public string Email_BCC { 114 | get { 115 | return ((string)(this["Email_BCC"])); 116 | } 117 | set { 118 | this["Email_BCC"] = value; 119 | } 120 | } 121 | 122 | [global::System.Configuration.UserScopedSettingAttribute()] 123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 124 | [global::System.Configuration.DefaultSettingValueAttribute(@"The information contained is intended for the named recipients only, it may contain confidential and/or legally privileged information and is only intended for the use of the person to whom it is addressed. If you have received this e-mail in error you must not copy, duplicate, forward, print or distribute any information contained herein, but must ensure that this e-mail is permanently deleted and advise the sender. ")] 125 | public string Email_Message_Body { 126 | get { 127 | return ((string)(this["Email_Message_Body"])); 128 | } 129 | set { 130 | this["Email_Message_Body"] = value; 131 | } 132 | } 133 | 134 | [global::System.Configuration.UserScopedSettingAttribute()] 135 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 136 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 137 | public bool Keep_Outputfile_after_Sending { 138 | get { 139 | return ((bool)(this["Keep_Outputfile_after_Sending"])); 140 | } 141 | set { 142 | this["Keep_Outputfile_after_Sending"] = value; 143 | } 144 | } 145 | 146 | [global::System.Configuration.UserScopedSettingAttribute()] 147 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 148 | [global::System.Configuration.DefaultSettingValueAttribute("")] 149 | public string Default_Printer_Name { 150 | get { 151 | return ((string)(this["Default_Printer_Name"])); 152 | } 153 | set { 154 | this["Default_Printer_Name"] = value; 155 | } 156 | } 157 | 158 | [global::System.Configuration.UserScopedSettingAttribute()] 159 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 160 | [global::System.Configuration.DefaultSettingValueAttribute("SQLSERVERNAME")] 161 | public string SQL_Server_Name { 162 | get { 163 | return ((string)(this["SQL_Server_Name"])); 164 | } 165 | set { 166 | this["SQL_Server_Name"] = value; 167 | } 168 | } 169 | 170 | [global::System.Configuration.UserScopedSettingAttribute()] 171 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 172 | [global::System.Configuration.DefaultSettingValueAttribute("SQLDBNAME")] 173 | public string SQL_Database_Name { 174 | get { 175 | return ((string)(this["SQL_Database_Name"])); 176 | } 177 | set { 178 | this["SQL_Database_Name"] = value; 179 | } 180 | } 181 | 182 | [global::System.Configuration.UserScopedSettingAttribute()] 183 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 184 | [global::System.Configuration.DefaultSettingValueAttribute("REPORTUSERNAME")] 185 | public string SQL_User_Name { 186 | get { 187 | return ((string)(this["SQL_User_Name"])); 188 | } 189 | set { 190 | this["SQL_User_Name"] = value; 191 | } 192 | } 193 | 194 | [global::System.Configuration.UserScopedSettingAttribute()] 195 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 196 | [global::System.Configuration.DefaultSettingValueAttribute("REPORTUSERPASSWORD")] 197 | public string SQL_Password { 198 | get { 199 | return ((string)(this["SQL_Password"])); 200 | } 201 | set { 202 | this["SQL_Password"] = value; 203 | } 204 | } 205 | 206 | [global::System.Configuration.UserScopedSettingAttribute()] 207 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 208 | [global::System.Configuration.DefaultSettingValueAttribute("USERNAME")] 209 | public string SMTP_User_Name { 210 | get { 211 | return ((string)(this["SMTP_User_Name"])); 212 | } 213 | set { 214 | this["SMTP_User_Name"] = value; 215 | } 216 | } 217 | 218 | [global::System.Configuration.UserScopedSettingAttribute()] 219 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 220 | [global::System.Configuration.DefaultSettingValueAttribute("PASSWORD")] 221 | public string SMTP_Password { 222 | get { 223 | return ((string)(this["SMTP_Password"])); 224 | } 225 | set { 226 | this["SMTP_Password"] = value; 227 | } 228 | } 229 | 230 | [global::System.Configuration.UserScopedSettingAttribute()] 231 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 232 | [global::System.Configuration.DefaultSettingValueAttribute("noreply@noreply.com")] 233 | public string Email_From { 234 | get { 235 | return ((string)(this["Email_From"])); 236 | } 237 | set { 238 | this["Email_From"] = value; 239 | } 240 | } 241 | 242 | [global::System.Configuration.UserScopedSettingAttribute()] 243 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 244 | [global::System.Configuration.DefaultSettingValueAttribute("NoReply")] 245 | public string Email_From_Display_Name { 246 | get { 247 | return ((string)(this["Email_From_Display_Name"])); 248 | } 249 | set { 250 | this["Email_From_Display_Name"] = value; 251 | } 252 | } 253 | 254 | [global::System.Configuration.UserScopedSettingAttribute()] 255 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 256 | [global::System.Configuration.DefaultSettingValueAttribute("Automated Crystal Reports")] 257 | public string Email_Subject { 258 | get { 259 | return ((string)(this["Email_Subject"])); 260 | } 261 | set { 262 | this["Email_Subject"] = value; 263 | } 264 | } 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/ArgumentContainer.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CrystalReportsNinja 9 | { 10 | public class ArgumentContainer 11 | { 12 | /// 13 | /// -I Use Integrated Security for Database Credentials 14 | /// 15 | public Boolean IntegratedSecurity { get; set; } 16 | 17 | /// 18 | /// -U Report database login username (mandatory unless integrated security login) 19 | /// 20 | public string UserName { get; set; } 21 | 22 | /// 23 | /// -P Report database login password (mandatory unless integrated security login) 24 | /// 25 | public string Password { get; set; } 26 | 27 | /// 28 | /// -F Crystal Report path and filename (mandatory) 29 | /// 30 | public string ReportPath { get; set; } 31 | 32 | /// 33 | /// -O Output file path and filename 34 | /// 35 | public string OutputPath { get; set; } 36 | 37 | /// 38 | /// -S Server name of specified crystal Report (mandatory) 39 | /// 40 | public string ServerName { get; set; } 41 | 42 | /// 43 | /// -D Database name of specified crystal Report 44 | /// 45 | public string DatabaseName { get; set; } 46 | 47 | /// 48 | /// -E Crystal Report exported format (pdf,xls,htm). "print" to print to printer 49 | /// 50 | public string OutputFormat { get; set; } 51 | 52 | /// 53 | /// -a Report Parameter set (small letter p). eg:{customer : "Microsoft Corporation"} or {customer : "Microsoft Corporation" | "Google Inc"} 54 | /// 55 | public List ParameterCollection { get; set; } 56 | 57 | /// 58 | /// To print or to export as file. true - print, false 59 | /// 60 | public bool PrintOutput { get; set; } 61 | 62 | /// 63 | /// -C number of copy to be printed out 64 | /// 65 | public int PrintCopy { get; set; } 66 | 67 | /// 68 | /// -N Printer name 69 | /// 70 | public string PrinterName { get; set; } 71 | 72 | /// To display Help message 73 | /// 74 | public bool GetHelp { get; set; } 75 | 76 | /// 77 | /// -M To Email out the report or not 78 | /// 79 | public bool EmailOutput { get; set; } 80 | 81 | /// 82 | /// -MF From Email Address. Defaults to noreply@noreply.com.au 83 | /// 84 | public string MailFrom { get; set; } 85 | 86 | /// 87 | /// -MN From Email Address. Defaults to Crystal Reports 88 | /// 89 | public string MailFromName { get; set; } 90 | /// 91 | /// -MT Email address to email to. (Mandatory for emailing report) 92 | /// 93 | public string MailTo { get; set; } 94 | 95 | /// 96 | /// -MC Email address to CC to. (Optional for emailing report) 97 | /// 98 | public string MailCC { get; set; } 99 | 100 | /// 101 | /// -MB Email address to Bcc to. (Optional for emailing report) 102 | /// 103 | public string MailBcc { get; set; } 104 | 105 | /// 106 | /// -MSA SMTP Address. (Mandatory for emailing report) 107 | /// 108 | public String SmtpServer { get; set; } 109 | 110 | /// 111 | /// -MSP SMTP Port. Defaults to Port 25 112 | /// 113 | public int SmtpPort { get; set; } 114 | 115 | /// 116 | /// -MSE SMTP Enable SSL. Defaults to False 117 | /// 118 | public Boolean SmtpSSL { get; set; } 119 | 120 | /// 121 | /// -MSC SMTP Use Current User Credentials. Defaults to False 122 | /// 123 | public Boolean SmtpAuth { get; set; } 124 | 125 | /// 126 | /// -MSU SMTP Username. 127 | /// 128 | public string SmtpUN { get; set; } 129 | 130 | /// 131 | /// -MSP SMTP Password. 132 | /// 133 | public string SmtpPW { get; set; } 134 | 135 | /// 136 | /// -MS Email Subject. Defaults to Crystal Reports 137 | /// 138 | public String EmailSubject { get; set; } 139 | 140 | /// 141 | /// -MI Email Body. 142 | /// 143 | public String EmailBody { get; set; } 144 | 145 | /// 146 | /// -MK Email Keep File. Defaults to false 147 | /// 148 | public Boolean EmailKeepFile { get; set; } 149 | 150 | /// 151 | /// -L To produce log file 152 | /// 153 | public bool EnableLog { get; set; } 154 | 155 | /// 156 | /// -LC Write log output to Console 157 | /// 158 | public bool EnableLogToConsole { get; set; } 159 | 160 | /// 161 | /// Log File Name 162 | /// 163 | public String LogFileName { get; set; } 164 | 165 | /// 166 | /// -NR To refresh report or not 167 | /// 168 | public bool Refresh { get; set; } 169 | 170 | /// 171 | /// -SF Report Selection Formula 172 | /// 173 | public string SelectionFormula { get; set; } 174 | 175 | public ArgumentContainer() 176 | { 177 | // Assigning default values 178 | GetHelp = false; 179 | 180 | //Report Config 181 | ReportPath = null; 182 | OutputPath = null; 183 | OutputFormat = null; 184 | PrintOutput = false; 185 | PrintCopy = 1; 186 | PrinterName = Properties.Settings.Default.Default_Printer_Name; 187 | Refresh = true; 188 | ///SelectionFormula = null; 189 | ///Culture = null; 190 | 191 | //SQL Server Config 192 | ServerName = Properties.Settings.Default.SQL_Server_Name; 193 | DatabaseName = Properties.Settings.Default.SQL_Database_Name; 194 | IntegratedSecurity = Properties.Settings.Default.SQL_Use_IntegratedSecurity; 195 | UserName = Properties.Settings.Default.SQL_User_Name; 196 | Password = Properties.Settings.Default.SQL_Password; 197 | 198 | //Email Config 199 | MailTo = null; 200 | EmailOutput = false; 201 | MailCC = Properties.Settings.Default.Email_CC; 202 | MailBcc = Properties.Settings.Default.Email_BCC; 203 | MailFrom = Properties.Settings.Default.Email_From; 204 | MailFromName = Properties.Settings.Default.Email_From_Display_Name; 205 | SmtpServer = Properties.Settings.Default.SMTP_Server_Address; 206 | SmtpPort = Convert.ToInt32(Properties.Settings.Default.SMTP_Server_Port); 207 | SmtpSSL = Properties.Settings.Default.SMTP_SSL_Reqruired; 208 | SmtpAuth = Properties.Settings.Default.SMTP_Authentication_Used; 209 | SmtpUN = Properties.Settings.Default.SMTP_User_Name; 210 | SmtpPW = Properties.Settings.Default.SMTP_Password; 211 | EmailSubject = Properties.Settings.Default.Email_Subject; 212 | EmailBody = Properties.Settings.Default.Email_Message_Body; 213 | EmailKeepFile = Properties.Settings.Default.Keep_Outputfile_after_Sending; 214 | 215 | //Logging Options 216 | EnableLog = false; 217 | LogFileName = String.Empty; 218 | EnableLogToConsole = Properties.Settings.Default.EnableLogToConsole; 219 | 220 | // Collection of string to store parameters 221 | ParameterCollection = new List(); 222 | } 223 | 224 | public void ReadArguments(string[] parameters) 225 | { 226 | if (parameters.Length == 0) 227 | //throw new Exception("No parameter is specified!"); 228 | GetHelp = true; 229 | 230 | #region Assigning crexport parameters to variables 231 | for (int i = 0; i < parameters.Count(); i++) 232 | { 233 | if (i + 1 < parameters.Count()) 234 | { 235 | if (parameters[i + 1].Length > 0) 236 | { 237 | if (parameters[i].ToUpper() == "-U") 238 | UserName = parameters[i + 1]; 239 | else if (parameters[i].ToUpper() == "-P") 240 | Password = parameters[i + 1]; 241 | else if (parameters[i].Equals("-I")) 242 | IntegratedSecurity = true; 243 | else if (parameters[i].ToUpper() == "-F") 244 | ReportPath = parameters[i + 1]; 245 | else if (parameters[i].ToUpper() == "-O") 246 | OutputPath = parameters[i + 1]; 247 | else if (parameters[i].ToUpper() == "-S") 248 | ServerName = parameters[i + 1]; 249 | else if (parameters[i].ToUpper() == "-D") 250 | DatabaseName = parameters[i + 1]; 251 | else if (parameters[i].ToUpper() == "-E") 252 | {OutputFormat = parameters[i + 1]; if (OutputFormat.ToUpper() == "PRINT") { PrintOutput = true; }} 253 | else if (parameters[i].ToUpper() == "-N") 254 | PrinterName = parameters[i + 1]; 255 | else if (parameters[i].ToUpper() == "-C") 256 | { 257 | try 258 | { 259 | PrintCopy = Convert.ToInt32(parameters[i + 1]); 260 | } 261 | catch (Exception ex) 262 | { throw ex; } 263 | } 264 | else if (parameters[i].ToUpper() == "-A") 265 | ParameterCollection.Add(parameters[i + 1]); 266 | 267 | //Email Config 268 | else if (parameters[i].ToUpper() == "-M") 269 | EmailOutput = true; 270 | else if (parameters[i].ToUpper() == "-MF") 271 | MailFrom = parameters[i + 1]; 272 | else if (parameters[i].ToUpper() == "-MN") 273 | MailFromName = parameters[i + 1]; 274 | else if (parameters[i].ToUpper() == "-MS") 275 | EmailSubject = parameters[i + 1]; 276 | else if (parameters[i].ToUpper() == "-MI") 277 | EmailBody = parameters[i + 1]; 278 | else if (parameters[i].ToUpper() == "-MT") 279 | MailTo = parameters[i + 1]; 280 | else if (parameters[i].ToUpper() == "-MC") 281 | MailCC = parameters[i + 1]; 282 | else if (parameters[i].ToUpper() == "-MB") 283 | MailBcc = parameters[i + 1]; 284 | else if (parameters[i].ToUpper() == "-MK") 285 | EmailKeepFile = true; 286 | else if (parameters[i].ToUpper() == "-MSA") 287 | SmtpServer = parameters[i + 1]; 288 | else if (parameters[i].ToUpper() == "-MSP") 289 | SmtpPort = Convert.ToInt32(parameters[i + 1]); 290 | else if (parameters[i].ToUpper() == "-MSE") 291 | SmtpSSL = true; 292 | else if (parameters[i].ToUpper() == "-MSC") 293 | SmtpAuth = true; 294 | else if (parameters[i].ToUpper() == "-MUN") 295 | SmtpUN = parameters[i + 1]; 296 | else if (parameters[i].ToUpper() == "-MPW") 297 | SmtpPW = parameters[i + 1]; 298 | else if (parameters[i].ToUpper() == "-SF") 299 | SelectionFormula = parameters[i + 1]; 300 | } 301 | } 302 | 303 | if (parameters[i] == "-?" || parameters[i] == "/?" || parameters[i] == "?") 304 | GetHelp = true; 305 | 306 | if (parameters[i].ToUpper() == "-L") 307 | EnableLog = true; 308 | 309 | if (parameters[i].ToUpper() == "-NR") 310 | Refresh = false; 311 | 312 | if (parameters[i].ToUpper() == "-LC") 313 | EnableLogToConsole = true; 314 | } 315 | #endregion 316 | } 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crystal Reports Ninja v1.10.0.0 2 | 3 | Forked from Tengyongs Crystal Reports Ninja. https://github.com/rainforestnet/CrystalReportsNinja 4 | 5 | Crystal Reports Ninja is an open source Windows application. The application loads and executes Crystal Report files exporting the results to a directoy or sending via email. 6 | 7 | The Crystal Reports Ninja application can be invoked using Windows PowerShell or Windows Command Prompt. 8 | 9 | ## Supported File Formats for Export 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 |
File typeDescriptions
txtPlain text file
pdfAdobe Portable Document format (pdf)
docMicrosoft Word
xlsxMicrosoft Excel
xlsMicrosoft Excel (Old Version)
xlsdataMicrosoft Excel with Data Only
rtfRich Text format
ertfEditable Rich Text format
tabTab delimited text file
csvComma delimited text file
xmlxml file
htmHTML file
rptCrystal Reports file
printPrint Crystal Report to a printer
77 | 78 | 79 | ## PreRequisites 80 | * .NET Framework 4.7.2 81 | * Crystal Reports Runtime 13.0.28 (or later). 82 | - If using the 64-bit Crystal Reports Ninja you must have the 64-bit Crystal Reports Runtime installed. 83 | - If using the 32-bit Crystal Reports Ninja you must have the 32-bit Crystal Reports Runtime installed. 84 | - Crystal Reports Runtime installation files can be downloaded from SAP using one of the following link. 85 | http://www.crystalreports.com/crystal-reports-visual-studio/ 86 | https://wiki.scn.sap.com/wiki/display/BOBJ/Crystal+Reports%2C+Developer+for+Visual+Studio+Downloads 87 | https://origin.softwaredownloads.sap.com/public/site/index.html 88 | - It is suggested that you uninstall any previous versions of Crystal Reports Runtime before installing the latest version. 89 | 90 | ## Installation 91 | * Copy all the files from either the 64-bit or 32-bit Deployment directories to a new local directory. 92 | * The Only Files required to actually run the CrystalReportsNinja.exe and CrystalReportsNinja.exe.config. 93 | 94 | ## CONFIG File - Default Settings for CrystalReportsNinja 95 | * CrystalReportsNinja has been updated to now utilise an external CONFIG file for default parameters rather then them being hardcoded 96 | * Modify the CrystalReportsNinja.exe.config with the required defaults. 97 | * You can now generate reports with minimal command line arguments, if arguments are supplied it will overide the CONFIG file settings. 98 | - eg: CrystalReportsNinja.exe -M -MT test@test.com -E pdf -F test.rpt \" -a Entity:01 -a Year:2021 -a Month:01 \" 99 | - This will run a report against the Config file DB, SMTP etc and send a PDF to requested email address. 100 | 101 | ## How to use with Windows PowerShell (NEW FEATURE IN 1.4.0.0) 102 | 103 | * Start by creating a new PowerShell script. Using the PowerShell ISE to create the script is prefered, but any text editor will do. There are a few examples of PowerShell scripts located in the Scripts directory. 104 | 105 | * Below I have included the basic steps that need to be coded into the PowerShell script to be able to run Crystal Reports Ninja. 106 | - 1 Reference the Crystal Reports Ninja executable. 107 | - 2 Create a new instance of the ReportProcessor object. 108 | - 3 Set appropriate arguments for desired results. The only argument that is required to be set is the ReportPath argument. 109 | - 4 Set any parameters required by the Crystal Report. 110 | - 5 Use the Report Processors Run method to have Crystal Reports Ninja begin its execution. 111 | 112 | * Example 1. Export results to Excel file using Report with Integrated Security. 113 | ``` 114 | [System.Reflection.Assembly]::LoadFile("C:\Program Files\CrystalReportsNinja\CrystalReportsNinja.exe") 115 | $ReportProcessor = New-Object CrystalReportsNinja.ReportProcessor 116 | $ReportProcessor.ReportArguments.EnableLogToConsole = $true 117 | $ReportProcessor.ReportArguments.OutputFormat = "xlsx" 118 | $ReportProcessor.ReportArguments.OutputPath = "c:\tmp\Test1" 119 | $ReportProcessor.ReportArguments.ParameterCollection.Add("@DaysToConsider:90") 120 | $ReportProcessor.ReportArguments.ParameterCollection.Add("@MaximumVariance:1") 121 | $ReportProcessor.ReportArguments.ReportPath = "C:\CrystalReports\CrystalReport1.rpt" 122 | $ReportProcessor.Run() 123 | ``` 124 | 125 | ## How to use with Windows Command Prompt 126 | 127 | Locate the folder of CrystalReportsNinja.exe and run CrystalReportsNinja -? 128 | The only mandatory argument is "-F", in which is for user to specify a Crystal Reports file. 129 | 130 | ### List of arguments 131 | 132 | * ----------- Report and Database Config -----------; 133 | * -F Crystal Reports Path and Filename. (Mandatory); 134 | * -S Database Server Name. (Optional if using Database Server set within the Crystal Report); 135 | * -D Database Name. (Optional if using Database Server set within the Crystal Report); 136 | * -U Database User Account. (Optional, If not set IntegratedSecurity is used); 137 | * -P Database User Account Password. (Optional, If not set IntegratedSecurity is used); 138 | * ------------------ Output Config -----------------; 139 | * -E Export Type. (pdf,doc,xls,xlsx,rtf,htm,rpt,txt,csv,print); 140 | * -O Output Path and Filename. (Not needed when printed); 141 | * -N Printer Name. (Required when Printing); 142 | * -C Number of copies to be printed. (Optional, Default: 1); 143 | * ------------- Parameters and Formulas -------------; 144 | * -A Parameter value.; (Optional); 145 | * -SF Crystal Reports Selection Forumula (Optional); 146 | * ----------------- Logging Config -----------------; 147 | * -L Write a log file. (Optional); 148 | * -LC Write log output to console; (Optional); 149 | * ------------------ Email Config ------------------; 150 | * -M Email Report Output. (Enable Email Support); 151 | * -MF Email Address to be SENT FROM. (Optional, Default: noreply@noreply.com); 152 | * -MN Email SENT FROM Display Name (Optional, Default: Crystal Reports) 153 | * -MT Email Address to SEND to. (Mandatory); 154 | * -MC Email Address to be CC'd. (Optional); 155 | * -MB Email Address to be BCC'd. (Optional); 156 | * -MS Email Subject Line of the Email. (Optional, Default: Crystal Reports); 157 | * -MI Email Message Body. (Optional) 158 | * -MSA SMTP server address. (Mandatory, if SSL enabled FQDN is required); 159 | * -MSP SMTP server port. (Optional, Default: 25); 160 | * -MSE SMTP server Enable SSL. (Optional, Default: False); 161 | * -MSC SMTP Auth - Use Current User Credentials, (Optional, Default: False ); 162 | * -MUN SMTP server Username. (Optional) \"domain\\username\"; 163 | * -MPW SMTP server Password. (Optional) \"password\"; 164 | * -MK Keep the generated file after sending email (Optional, Boolean True/False) 165 | 166 | ### -F, Crystal Reports source file 167 | This is the only mandatory (must specify) argument, it allows your to specify the Crystal Reports filename to be exported. 168 | 169 | ### -S, Server name or Data Source name 170 | Most of the time, you need not specify the server name or data source name of your Crystal Reports file as every Crystal Reports file saves data source information during design time. 171 | 172 | Therefore, you only specify a server name when you want Crystal Reports to retrieve data from another data source that is different from what it is saved in Crystal Reports file during design time. 173 | 174 | If your crystal Reports data source is one of the ODBC DSN (regardless of User DSN or System DSN), the DSN will be your Server Name (-S). 175 | 176 | ### -D, Database name 177 | Similarly to Server Name. Database Name is completely optional. You only specify a Database Name when you intend to retrieve data from another database that is different from default database name that is saved in Crystal Reports file. 178 | 179 | ### -U and - P, Username and Password to login to Data source 180 | If you are using database like Microsoft SQL server, MySQL or Oracle, you are most likely required to supply a username and password to login to database. 181 | 182 | If you are using trusted connection to your SQL server, you wouldn't need to supply username and password when you run CrystalReportsNinja. 183 | 184 | If you are using a password protected Microsoft Access database, you need only to specify password and not username. 185 | 186 | ### -E, Crystal Reports Export File Type 187 | Use -E to specify desired file format. There are 13 file formats that you can export a Crystal Reports file. If -E argument is not supplied, CrystalReportsNinja will look into the output file extension. If output file is report1.pdf, it will then set to be Adobe PDF format. If file extension cannot be mapped into supported file format, CrystalReportsNinja will export your Crystal Reports into plain text file. 188 | 189 | ### -O, Crystal Reports output file 190 | If -O is not specified, Crystal Reports Exporter will just export the Crystal Reports into the same directory when Crystal Reports source file is resided. 191 | 192 | The filename of the exported file is the same as Crystal Report source file and ending with timestamp (yyyyMMddHHmmss). 193 | 194 | ### -N, Printer Name 195 | Network printer : \\\\PrintServer\\Printername or Local printer : printername. 196 | 197 | ### -C, Copies to Print 198 | Number of copies to print to printer. 199 | 200 | ### -A Passing in Parameters of Crystal Reports 201 | Parameters within the Crystal Report that you would like to pass a value to. Case must match. 202 | 203 | ### -L Write Log File 204 | filename ninja-yyyyMMddHHmmss.log 205 | 206 | ### -LC Write Log Output to Console 207 | 208 | 209 | ### -SF, Crystal Reports Selection Formula 210 | The Crystal Reports Record Selection Formula to use. The result of the formula must be boolean (at least as far as I can tell). You can find the field name to use by opening the Crystal Report, right clicking the field and selecting 'Find in Formulas'. The field name will be displayed next to the "Matches for". 211 | 212 | ### -M Email Report 213 | 214 | ### -MF From Email Address 215 | The email address that the email will appear to be from. Defaults to CrystalReportsNinja@noreply.com. 216 | 217 | ### -MN From Email Address Display Nmae 218 | The display name that the email will appear to be from. 219 | 220 | ### -MT To Email Address 221 | The email address that the email will be sent to. Mandatory for Email Report. 222 | 223 | ### -MS Subject 224 | The text that will appear in the subject line of the email. Defaults to Crystal Reports Ninja. 225 | 226 | ### -MI Email Message Body 227 | The text that will appear in the body of the email. 228 | 229 | ### -MSA SMTP Server 230 | SMTP server address. Mandatory for Email Report. 231 | 232 | ### -MK Keep the generated file after sending by email 233 | This is a boolean that will determine if the generated report should be kept after sending by email. Setting ```-MK True``` will keep the generated file after sending by email. 234 | 235 | 236 | 237 | ###Example 1 238 | Let's take an example of a Crystal Reports file test.rpt located in C: root directory. The Crystal Reports file has two parameters, namely Supplier and Date Range. 239 | ``` 240 | c:\>CrystalReportsNinja -U user1 -P mypass -S server1 -D Demo 241 | -F c:\test.rpt -O d:\test.pdf -E pdf -a "Supplier:Active Outdoors" 242 | -a "Date Range:(12-01-2001,12-04-2002)" 243 | ``` 244 | 245 | Rule to pass parameters 246 | Use double quote (") to enclose the parameter string (parameter name and parameter value) 247 | A colon (:) must be placed between parameter name and parameter value. 248 | Use comma (,) to separate start value and end value of a Range parameter. 249 | Use pipe (|) to pass multiple values into the same parameter. 250 | Parameter name is case sensitive 251 | 252 | ###Example 2 253 | The following crystal Reports "testTraining.rpt" has 5 discrete parameters and 2 range parameters. 254 | Discrete parameters are: 255 | * company 256 | * customer 257 | * branch 258 | 259 | Range parameters are: 260 | * Daterange 261 | * Product 262 | 263 | Example of Single value parameters : 264 | 265 | ``` 266 | c:\>CrystalReportsNinja -U user1 -P secret -F C:\Creport\Statement.rpt 267 | -O D:\Output\Statement.pdf -E pdf -S"AnySystem DB" 268 | -a "company:The One Computer,Inc" -a "customer:"MyBooks Store" 269 | -a "branch:Malaysia" -a "daterange:(12-01-2001,12-04-2002)" 270 | -a "productrange:(AFD001,AFD005)" 271 | ``` 272 | 273 | Example of Multiple values parameters (without any ranges): 274 | ``` 275 | c:\>CrystalReportsNinja -F testreport.rpt -O testOutput.xls 276 | -E xlsdata -S order.mdb -a "dates:(25-12-2001)|(25-12-2002)|25-12-2003)" 277 | -a "Clients:(Ace Soft Inc)|(Xtreme Bike Inc)" 278 | ``` 279 | 280 | Example of Multiple values parameters (with ranges) : 281 | ``` 282 | c:\>CrystalReportsNinja -F testreport.rpt -O testOutput.xls 283 | -E xlsdata -S order.mdb -a "dateRanges:(01-01-2001,28-02-2001)|(02-01-2002,31-10-2002)|(02-08-2002,31-12-2002)" 284 | -a "ClientRanges:(Ace Soft Inc,Best Computer Inc)|(Xtreme Bike Inc,Zebra Design Inc)" 285 | ``` 286 | 287 | Example to print Crystal Reports output to printer 288 | ``` 289 | c:\>CrystalReportsNinja -F report101.rpt -E print -N "HP LaserJet 1200" -C 3 290 | ``` 291 | 292 | Email Report Example 293 | ``` 294 | c:\>CrystalReportsNinja -F Z:\CrystalReportsNinja\CrystalReports\ConsignaStoreInventoryValue.rpt -E pdf -O Z:\CrystalReportsNinja\Output\Test.pdf -a "@CustomerId:12345" -a "@Warehouse:987" -M -MF "Report1@company.com" -MT "good_user@company.com" -MS "Testing Ninja" -MSA "mail.company.com" 295 | ``` 296 | 297 | ## Troubleshooting Ninja 298 | Check the ensure that the version of Ninja (64bit\32bit) you are using matches the version of the ODBC Driver (64bit\32bit) you are using. FYI, as of Oct 2019 the Crystal Reports Developer application is still 32bit. 299 | 300 | Make sure that the option to save data in the Crystal Report is not enabled. Users have reported issues when this option is enabled. 301 | 302 | I had an issue with SQLs written by Crystal Reports working in Developer but not in Ninja. The problem had to do with fully qualified table names. To solve the problem I switched out the SQL Crystal had written and replaced it with a stored procedure which fixed the problem for me. There are other solutions to this problem. This webpage helped when I was searching for solutions to the problem. https://wisdomofsolomon.wordpress.com/2011/06/18/crystal-reports-tables-not-found-during-verify-database/ 303 | 304 | ## License 305 | [MIT License](https://en.wikipedia.org/wiki/MIT_License) 306 | -------------------------------------------------------------------------------- /Source/CrystalReportsNinja/ReportProcessor.cs: -------------------------------------------------------------------------------- 1 | using CrystalDecisions.CrystalReports.Engine; 2 | using CrystalDecisions.Shared; 3 | using System; 4 | using System.IO; 5 | using System.Net.Mail; 6 | 7 | namespace CrystalReportsNinja 8 | { 9 | public class ReportProcessor 10 | { 11 | private string _sourceFilename; 12 | private string _outputFilename; 13 | private string _outputFormat; 14 | private bool _printToPrinter; 15 | 16 | private ReportDocument _reportDoc; 17 | private LogWriter _logger; 18 | 19 | public ArgumentContainer ReportArguments { get; set; } 20 | 21 | /// 22 | /// Constructor 23 | /// 24 | public ReportProcessor() 25 | { 26 | ReportArguments = new ArgumentContainer(); 27 | 28 | _reportDoc = new ReportDocument(); 29 | } 30 | 31 | /// 32 | /// Load external Crystal Report file into Report Document 33 | /// 34 | private void LoadReport() 35 | { 36 | _sourceFilename = ReportArguments.ReportPath.Trim(); 37 | if (_sourceFilename == null || _sourceFilename == string.Empty) 38 | { 39 | throw new Exception("Invalid Crystal Reports file"); 40 | } 41 | 42 | if (_sourceFilename.LastIndexOf(".rpt") == -1) 43 | throw new Exception("Invalid Crystal Reports file"); 44 | 45 | _reportDoc.Load(_sourceFilename, OpenReportMethod.OpenReportByDefault); 46 | var filenameOnly = System.IO.Path.GetFileNameWithoutExtension(_sourceFilename); 47 | _logger.Write(string.Format("Report {0}.rpt loaded successfully", filenameOnly)); 48 | } 49 | 50 | /// 51 | /// Match User input parameter values with Report parameters 52 | /// 53 | private void ProcessParameters() 54 | { 55 | var paramCount = _reportDoc.ParameterFields.Count; 56 | _logger.Write(string.Format("Number of Parameters detected in the report = {0}", _reportDoc.ParameterFields.Count)); 57 | if (_reportDoc.DataDefinition.ParameterFields.Count > 0) 58 | { 59 | ParameterCore paraCore = new ParameterCore(ReportArguments.LogFileName, ReportArguments); 60 | paraCore.ProcessRawParameters(); 61 | _logger.Write(string.Format("")); 62 | foreach (ParameterFieldDefinition _ParameterFieldDefinition in _reportDoc.DataDefinition.ParameterFields) 63 | { 64 | if (!_ParameterFieldDefinition.IsLinked()) 65 | { 66 | _logger.Write(string.Format("Applied Parameter '{0}' as MultiValue '{1}'", _ParameterFieldDefinition.Name, _ParameterFieldDefinition.EnableAllowMultipleValue)); 67 | ParameterValues values = paraCore.GetParameterValues(_ParameterFieldDefinition); 68 | _ParameterFieldDefinition.ApplyCurrentValues(values); 69 | } 70 | else 71 | _logger.Write(string.Format("Skipped '{1}' as MultiValue '{2}' Parameter in SubReport = '{0}' as its Linked to Main Report", _ParameterFieldDefinition.ReportName, _ParameterFieldDefinition.Name, _ParameterFieldDefinition.EnableAllowMultipleValue)); 72 | _logger.Write(string.Format("")); 73 | } 74 | } 75 | } 76 | 77 | /// 78 | /// Add selection formula to ReportDocument 79 | /// 80 | private void ProcessSelectionFormula() 81 | { 82 | if (!String.IsNullOrWhiteSpace(ReportArguments.SelectionFormula)) 83 | { 84 | _reportDoc.RecordSelectionFormula = ReportArguments.SelectionFormula; 85 | } 86 | } 87 | 88 | /// 89 | /// Validate configurations related to program output. 90 | /// 91 | /// 92 | /// Program output can be TWO forms 93 | /// 1. Export as a file 94 | /// 2. Print to printer 95 | /// 96 | private void ValidateOutputConfigurations() 97 | { 98 | _outputFilename = ReportArguments.OutputPath; 99 | _outputFormat = ReportArguments.OutputFormat; 100 | _printToPrinter = ReportArguments.PrintOutput; 101 | 102 | bool specifiedFileName = _outputFilename != null ? true : false; 103 | bool specifiedFormat = _outputFormat != null ? true : false; 104 | 105 | if (!_printToPrinter) 106 | { 107 | string fileExt = ""; 108 | 109 | //default set to text file 110 | if (!specifiedFileName && !specifiedFormat) 111 | _outputFormat = "txt"; 112 | fileExt = "txt"; 113 | // Use output format to set output file name extension 114 | if (specifiedFormat) 115 | { 116 | if (_outputFormat.ToUpper() == "XLSDATA") 117 | fileExt = "xls"; 118 | else if (_outputFormat.ToUpper() == "TAB") 119 | fileExt = "txt"; 120 | else if (_outputFormat.ToUpper() == "ERTF") 121 | fileExt = "rtf"; 122 | else if (_outputFormat.ToUpper() == "HTM") 123 | fileExt = "html"; 124 | else 125 | fileExt = _outputFormat; 126 | } 127 | 128 | // Use output file name extension to set output format 129 | if (specifiedFileName && !specifiedFormat) 130 | { 131 | int lastIndexDot = _outputFilename.LastIndexOf("."); 132 | if (_outputFilename.Length == lastIndexDot + 4) 133 | { 134 | fileExt = _outputFilename.Substring(lastIndexDot + 1, 3); 135 | 136 | //ensure filename extension has 3 char after the dot (.) 137 | if (fileExt.ToUpper() == "RTF" || fileExt.ToUpper() == "TXT" || fileExt.ToUpper() == "CSV" || fileExt.ToUpper() == "PDF" || fileExt.ToUpper() == "RPT" || fileExt.ToUpper() == "DOC" || fileExt.ToUpper() == "XLS" || fileExt.ToUpper() == "XML" || fileExt.ToUpper() == "HTM") 138 | _outputFormat = _outputFilename.Substring(lastIndexDot + 1, 3); 139 | } 140 | else if (_outputFilename.Length == lastIndexDot + 5) 141 | { 142 | fileExt = _outputFilename.Substring(lastIndexDot + 1, 4); // Fix for file ext has 4 char 143 | if (fileExt.ToUpper() == "XLSX" || fileExt.ToUpper() == "HTML") 144 | _outputFormat = _outputFilename.Substring(lastIndexDot + 1, 4); 145 | } 146 | } 147 | // Use output file name and extension to set output format and Name if Matching criteria 148 | if (specifiedFileName && specifiedFormat) 149 | { 150 | int lastIndexDot = _outputFilename.LastIndexOf("."); 151 | if ((_outputFilename.Length == lastIndexDot + 4) && (fileExt.ToUpper() != _outputFilename.Substring(lastIndexDot + 1, 3).ToUpper())) //file ext has 3 char 152 | { 153 | _outputFilename = string.Format("{0}.{1}", _outputFilename, fileExt); 154 | } 155 | else if ((_outputFilename.Length == lastIndexDot + 5) && (fileExt.ToUpper() != _outputFilename.Substring(lastIndexDot + 1, 4).ToUpper())) //file ext has 4 char 156 | { 157 | _outputFilename = string.Format("{0}.{1}", _outputFilename, fileExt); 158 | } 159 | } 160 | 161 | if (!specifiedFileName) 162 | _outputFilename = String.Format("{0}-{1}.{2}", _sourceFilename.Substring(0, _sourceFilename.LastIndexOf(".rpt")), DateTime.Now.ToString("yyyyMMddHHmmss"), fileExt); 163 | 164 | _logger.Write(string.Format("Output Filename : {0}", _outputFilename)); 165 | _logger.Write(string.Format("Output Format : {0}", _outputFormat)); 166 | } 167 | } 168 | 169 | /// 170 | /// Perform Login to database tables 171 | /// 172 | private void PerformDBLogin() 173 | { 174 | if (ReportArguments.Refresh) 175 | { 176 | TableLogOnInfo logonInfo; 177 | foreach (Table table in _reportDoc.Database.Tables) 178 | { 179 | logonInfo = table.LogOnInfo; 180 | if (!String.IsNullOrWhiteSpace(ReportArguments.ServerName)) 181 | { logonInfo.ConnectionInfo.ServerName = ReportArguments.ServerName; } 182 | 183 | if (!String.IsNullOrWhiteSpace(ReportArguments.DatabaseName)) 184 | { logonInfo.ConnectionInfo.DatabaseName = ReportArguments.DatabaseName; } 185 | 186 | if (ReportArguments.IntegratedSecurity) 187 | { 188 | logonInfo.ConnectionInfo.IntegratedSecurity = true; 189 | _logger.Write(string.Format("Logging into {1} Database on {0} with Integrated Security = {2}", logonInfo.ConnectionInfo.ServerName, logonInfo.ConnectionInfo.DatabaseName, logonInfo.ConnectionInfo.IntegratedSecurity)); 190 | } 191 | else 192 | { 193 | if (!String.IsNullOrWhiteSpace(ReportArguments.UserName)) 194 | { logonInfo.ConnectionInfo.UserID = ReportArguments.UserName; } 195 | if (!String.IsNullOrWhiteSpace(ReportArguments.Password)) 196 | { logonInfo.ConnectionInfo.Password = ReportArguments.Password; } 197 | ///_logger.Write(string.Format("Logging into {1} Database on {0} with User id: {2} and PW: {3} with Integrated Security = {4}", logonInfo.ConnectionInfo.ServerName, logonInfo.ConnectionInfo.DatabaseName, logonInfo.ConnectionInfo.UserID, logonInfo.ConnectionInfo.Password, logonInfo.ConnectionInfo.IntegratedSecurity)); 198 | _logger.Write(string.Format("Logging into {1} Database on {0} with User id: {2} with Integrated Security = {3}", logonInfo.ConnectionInfo.ServerName, logonInfo.ConnectionInfo.DatabaseName, logonInfo.ConnectionInfo.UserID, logonInfo.ConnectionInfo.IntegratedSecurity)); 199 | } 200 | table.ApplyLogOnInfo(logonInfo); 201 | } 202 | } 203 | } 204 | 205 | /// 206 | /// Set export file type or printer to Report Document object. 207 | /// 208 | private void ApplyReportOutput() 209 | { 210 | if (_printToPrinter) 211 | { 212 | var printerName = ReportArguments.PrinterName != null ? ReportArguments.PrinterName.Trim() : ""; 213 | _logger.Write(string.Format("The default printer set in the Report is '{0}'", _reportDoc.PrintOptions.PrinterName)); 214 | if (printerName.Length > 0 && printerName.ToUpper() != "DFLT") 215 | //Print to the Specified Printer 216 | { 217 | _reportDoc.PrintOptions.NoPrinter = false; //Changes the report option "No Printer: Optimized for Screen" 218 | _reportDoc.PrintOptions.PrinterName = printerName; 219 | _logger.Write(string.Format("The Specified PrinterName '{0}' is set by Parameter will be used", printerName)); 220 | } 221 | else if (_reportDoc.PrintOptions.PrinterName.Length > 0 && printerName.ToUpper() == "DFLT") 222 | //Print to the reports default Printer 223 | { 224 | _reportDoc.PrintOptions.NoPrinter = false; //Changes the report option "No Printer: Optimized for Screen" 225 | _logger.Write(string.Format("The Specified PrinterName '{0}' is set in the report and DFLT flag will be used", _reportDoc.PrintOptions.PrinterName)); 226 | } 227 | else 228 | //Print to the Windows default Printer 229 | { 230 | System.Drawing.Printing.PrinterSettings prinSet = new System.Drawing.Printing.PrinterSettings(); 231 | _logger.Write(string.Format("Printer is not specified - The Windows Default Printer '{0}' will be used", prinSet.PrinterName)); 232 | if (prinSet.PrinterName.Trim().Length > 0) 233 | { 234 | _reportDoc.PrintOptions.NoPrinter = false; //Changes the report option "No Printer: Optimized for Screen" 235 | _reportDoc.PrintOptions.PrinterName = prinSet.PrinterName; 236 | } 237 | else 238 | throw new Exception("No printer name is specified"); 239 | } 240 | } 241 | else 242 | { 243 | if (_outputFormat.ToUpper() == "RTF") 244 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.RichText; 245 | else if (_outputFormat.ToUpper() == "TXT") 246 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.Text; 247 | else if (_outputFormat.ToUpper() == "TAB") 248 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.TabSeperatedText; 249 | else if (_outputFormat.ToUpper() == "CSV") 250 | { 251 | CharacterSeparatedValuesFormatOptions csvExpOpts = new CharacterSeparatedValuesFormatOptions(); 252 | csvExpOpts.ExportMode = CsvExportMode.Standard; 253 | csvExpOpts.GroupSectionsOption = CsvExportSectionsOption.Export; 254 | csvExpOpts.ReportSectionsOption = CsvExportSectionsOption.Export; 255 | csvExpOpts.GroupSectionsOption = CsvExportSectionsOption.ExportIsolated; 256 | csvExpOpts.ReportSectionsOption = CsvExportSectionsOption.ExportIsolated; 257 | csvExpOpts.SeparatorText = ","; 258 | csvExpOpts.Delimiter = "\""; 259 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.CharacterSeparatedValues; 260 | _reportDoc.ExportOptions.FormatOptions = csvExpOpts; 261 | } 262 | else if (_outputFormat.ToUpper() == "PDF") 263 | { 264 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.PortableDocFormat; 265 | 266 | var grpCnt = _reportDoc.DataDefinition.Groups.Count; 267 | 268 | if (grpCnt > 0) 269 | _reportDoc.ExportOptions.ExportFormatOptions = new PdfFormatOptions { CreateBookmarksFromGroupTree = true }; 270 | } 271 | else if (_outputFormat.ToUpper() == "RPT") 272 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.CrystalReport; 273 | else if (_outputFormat.ToUpper() == "DOC") 274 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.WordForWindows; 275 | else if (_outputFormat.ToUpper() == "XLS") 276 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.Excel; 277 | else if (_outputFormat.ToUpper() == "XLSDATA") 278 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.ExcelRecord; 279 | else if (_outputFormat.ToUpper() == "XLSX") 280 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.ExcelWorkbook; 281 | else if (_outputFormat.ToUpper() == "ERTF") 282 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.EditableRTF; 283 | else if (_outputFormat.ToUpper() == "XML") 284 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.Xml; 285 | else if (_outputFormat.ToUpper() == "HTM" || _outputFormat.ToUpper() == "HTML") 286 | { 287 | HTMLFormatOptions htmlFormatOptions = new HTMLFormatOptions(); 288 | 289 | if (_outputFilename.LastIndexOf("\\") > 0) //if absolute output path is specified 290 | htmlFormatOptions.HTMLBaseFolderName = _outputFilename.Substring(0, _outputFilename.LastIndexOf("\\")); 291 | 292 | htmlFormatOptions.HTMLFileName = _outputFilename; 293 | htmlFormatOptions.HTMLEnableSeparatedPages = false; 294 | htmlFormatOptions.HTMLHasPageNavigator = true; 295 | htmlFormatOptions.FirstPageNumber = 1; 296 | _reportDoc.ExportOptions.ExportFormatType = ExportFormatType.HTML40; 297 | _reportDoc.ExportOptions.FormatOptions = htmlFormatOptions; 298 | } 299 | } 300 | } 301 | 302 | /// 303 | /// Refresh Crystal Report if no input of parameters 304 | /// 305 | private void PerformRefresh() 306 | { 307 | bool toRefresh = ReportArguments.Refresh; 308 | bool noParameter = (_reportDoc.ParameterFields.Count == 0) ? true : false; 309 | 310 | if (toRefresh && noParameter) 311 | _reportDoc.Refresh(); 312 | } 313 | 314 | /// 315 | /// Print or Export Crystal Report 316 | /// 317 | private void PerformOutput() 318 | { 319 | if (_printToPrinter) 320 | { 321 | var copy = ReportArguments.PrintCopy; 322 | _reportDoc.PrintToPrinter(copy, true, 0, 0); 323 | _logger.Write(string.Format("Report printed to : {0} - {1} Copies", _reportDoc.PrintOptions.PrinterName,copy)); 324 | } 325 | else 326 | { 327 | _reportDoc.ExportOptions.ExportDestinationType = ExportDestinationType.DiskFile; 328 | 329 | DiskFileDestinationOptions diskOptions = new DiskFileDestinationOptions(); 330 | _reportDoc.ExportOptions.DestinationOptions = diskOptions; 331 | diskOptions.DiskFileName = _outputFilename; 332 | 333 | _reportDoc.Export(); 334 | _logger.Write(string.Format("Report exported to : {0}", _outputFilename)); 335 | 336 | if (ReportArguments.EmailOutput) 337 | { 338 | using (MailMessage _MailMessage = new MailMessage()) 339 | { 340 | _MailMessage.Attachments.Add(new Attachment(_outputFilename)); 341 | _MailMessage.From = new MailAddress(ReportArguments.MailFrom, ReportArguments.MailFromName); 342 | _MailMessage.Subject = ReportArguments.EmailSubject; 343 | if (ReportArguments.EmailBody != "NA") 344 | { 345 | _MailMessage.Body = ReportArguments.EmailBody; 346 | } 347 | _MailMessage.To.Add(ReportArguments.MailTo); 348 | if (ReportArguments.MailCC != "NA") 349 | { 350 | _MailMessage.CC.Add(ReportArguments.MailCC); 351 | } 352 | if (ReportArguments.MailBcc != "NA") 353 | { 354 | _MailMessage.Bcc.Add(ReportArguments.MailBcc); 355 | } 356 | SmtpClient smtpClient = new SmtpClient(); 357 | smtpClient.Host = ReportArguments.SmtpServer; 358 | smtpClient.Port = ReportArguments.SmtpPort; 359 | smtpClient.EnableSsl = ReportArguments.SmtpSSL; 360 | 361 | ///if (ReportArguments.SmtpUN != null && ReportArguments.SmtpPW != null) 362 | if (ReportArguments.SmtpAuth == true) 363 | { 364 | //Uses Specified credentials to send email 365 | smtpClient.UseDefaultCredentials = true; 366 | System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(ReportArguments.SmtpUN, ReportArguments.SmtpPW); 367 | smtpClient.Credentials = credentials; 368 | } 369 | else 370 | { 371 | //If Set - uses the currently logged in user credentials to send email otherwise sent using Anonymous 372 | smtpClient.UseDefaultCredentials = ReportArguments.SmtpAuth; 373 | } 374 | smtpClient.Send(_MailMessage); 375 | _logger.Write(string.Format("Report {0} Emailed to : {1} CC'd to: {2} BCC'd to: {3}", _outputFilename, ReportArguments.MailTo, ReportArguments.MailCC, ReportArguments.MailBcc)); 376 | _logger.Write(string.Format("SMTP Details: Server:{0}, Port:{1}, SSL:{2} Auth:{3}, UN:{4}", smtpClient.Host, smtpClient.Port, smtpClient.EnableSsl, ReportArguments.SmtpAuth, ReportArguments.SmtpUN)); 377 | } 378 | 379 | if (!ReportArguments.EmailKeepFile) 380 | { File.Delete(_outputFilename); } 381 | } 382 | } 383 | Console.WriteLine("Completed"); 384 | } 385 | 386 | /// 387 | /// Run the Crystal Reports Exporting or Printing process. 388 | /// 389 | public void Run() 390 | { 391 | try 392 | { 393 | _logger = new LogWriter(ReportArguments.LogFileName, ReportArguments.EnableLogToConsole); 394 | _logger.Write(string.Format("")); 395 | _logger.Write(string.Format("================== LoadReport, Output File and DB logion ===========")); 396 | LoadReport(); 397 | ValidateOutputConfigurations(); 398 | 399 | PerformDBLogin(); 400 | ApplyReportOutput(); 401 | _logger.Write(string.Format("")); 402 | _logger.Write(string.Format("================== ProcessParameters ===============================")); 403 | ProcessParameters(); 404 | ProcessSelectionFormula(); 405 | 406 | PerformRefresh(); 407 | _logger.Write(string.Format("")); 408 | _logger.Write(string.Format("================== STEP = PerformOutput ============================")); 409 | PerformOutput(); 410 | } 411 | catch (Exception ex) 412 | { 413 | _logger.Write(string.Format("")); 414 | _logger.Write(string.Format("===================Logs and Errors =================================")); 415 | _logger.Write(string.Format("Message: {0}", ex.Message)); 416 | _logger.Write(string.Format("HResult: {0}", ex.HResult)); 417 | _logger.Write(string.Format("Data: {0}", ex.Data)); 418 | _logger.Write(string.Format("Inner Exception: {0}", ex.InnerException)); 419 | _logger.Write(string.Format("StackTrace: {0}", ex.StackTrace)); 420 | _logger.Write(string.Format("====================================================================")); 421 | throw; 422 | } 423 | finally 424 | { 425 | _reportDoc.Close(); 426 | } 427 | } 428 | } 429 | } 430 | --------------------------------------------------------------------------------