Beispiel #1
0
 /// <summary>
 /// Removes the dependency of the referenced file from the <paramref name="targetProject"/>.
 /// </summary>
 /// <param name="targetProject"><see cref="ExcelVbaProject"/> to remove reference from.</param>
 /// <param name="reference"><see cref="ExcelVbaReference"/> to remove.</param>
 /// <returns></returns>
 public bool TryRemoveReference(ref ExcelVbaProject targetProject, ExcelVbaReference reference)
 {
     try
     {
         _logger.Log($"Removing reference \"{reference.Name}\" from \"{targetProject.Name}\"");
         targetProject.References.Remove(reference);
         return(true);
     }
     catch (Exception ex)
     {
         throw;
     }
 }
Beispiel #2
0
        /// <summary>
        /// Create an empty VBA project.
        /// </summary>
        public void CreateVBAProject()
        {
#if !MONO && !CORECLR
            if (_vba != null || _package.Package.PartExists(new Uri(ExcelVbaProject.PartUri, UriKind.Relative)))
            {
                throw (new InvalidOperationException("VBA project already exists."));
            }

            _vba = new ExcelVbaProject(this);
            _vba.Create();
#else
            throw new NotSupportedException("Creating a VBA project is not supported under Mono.");
#endif
        }
Beispiel #3
0
        public void Dispose()
        {
            _sharedStrings.Clear();
            _sharedStringsList.Clear();

            _sharedStrings     = null;
            _sharedStringsList = null;
            _vba = null;
            _worksheets.Dispose();
            _package       = null;
            _worksheets    = null;
            _properties    = null;
            _formulaParser = null;
        }
Beispiel #4
0
 /// <summary>
 /// Attempts to add the <paramref name="modules"/> to the <paramref name="targetProject"/>. This overwrites the <paramref name="targetProject"/>'s internal <see cref="ExcelVbaProject.Modules"/> collection, as it doesn't support a "Merge" operation.
 /// </summary>
 /// <param name="targetProject"><see cref="ExcelVbaProject"/> to "merge" <paramref name="modules"/> into.</param>
 /// <param name="modules">Collection of <see cref="ExcelVBAModule"/>s to merge into <paramref name="targetProject"/></param>
 /// <returns></returns>
 public bool TryAddToProject(ref ExcelVbaProject targetProject, IEnumerable <ExcelVBAModule> modules)
 {
     //	Could create instance of _list and actually add to the collection, rather than replacing it entirely.
     //	This would require a rewrite of TryMergeModules as it currently collects the targetProject's modules as well.
     try
     {
         //	Let's get reflecting! Set the internal collection of modules on the target.
         targetProject.Modules.GetType().GetField("_list", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.SetValue(targetProject.Modules, modules.ToList());
         _logger.Log($"Added the following to target \"{targetProject.Name}\":\n\t{String.Join("\n\t", modules.Select(x => x.Name))}");
         return(true);
     }
     catch (Exception ex)
     {
         throw;
     }
 }
Beispiel #5
0
        /// <summary>
        /// Merges required non-Excel file references that are referenced by referenced files.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="references"></param>
        /// <remarks>For example, if a reference needs Microsoft Scripting Runtime 5.3, we want the resulting bundled project to have it as well.</remarks>
        /// <returns></returns>
        public bool TryMergeSystemReferences(ref ExcelVbaProject project, IEnumerable <ExcelVbaReference> references)
        {
            foreach (var reference in references)
            {
                //	Should not be adding Excel files
                if (reference.ReferenceRecordID == 14)
                {
                    continue;
                }

                //	No need to add the same reference.
                if (project.References.Any(x => x.Libid.Equals(reference.Libid, StringComparison.CurrentCultureIgnoreCase) && x.Name.Equals(reference.Name, StringComparison.CurrentCultureIgnoreCase)))
                {
                    continue;
                }

                project.References.Add(reference);
            }
            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Returns two distinct sets of references from the <see cref="ExcelVbaProject"/> <paramref name="project"/>, system references and Excel file references.
        /// </summary>
        /// <param name="project"><see cref="ExcelVbaProject"/> to extract references from.</param>
        /// <returns></returns>
        public (IEnumerable <ExcelVbaReference> System, IEnumerable <ExcelVbaReference> Excel) GetReferences(ExcelVbaProject project)
        {
            var systemReferences = project.References.Where(x => x.ReferenceRecordID != 14).ToList();
            var excelReferences  = project.References.Where(x => x.ReferenceRecordID == 14).ToList();

            if (excelReferences.Count > 0)
            {
                _logger.Log($"Found References:\n\t{String.Join("\n\t", excelReferences.Select(x => x.Name))}");
            }
            else
            {
                _logger.Log($"No references found for {project.Name}");
            }
            return(systemReferences, excelReferences);
        }
Beispiel #7
0
        /// <summary>
        /// Gathers all modules and class modules from the <paramref name="sourceProject"/> and <paramref name="targetProject"/> and merges them together.
        /// </summary>
        /// <param name="sourceProject">Project containing modules to be merged into <paramref name="targetProject"/>.</param>
        /// <param name="targetProject">Project containing existing modules.</param>
        /// <param name="modules">Combined modules.</param>
        /// <remarks>This will replace early binding references with <paramref name="sourceProject"/> module name if found, and will prompt if a module with the same name but different code exists.</remarks>
        /// <returns>True if merge was successful.</returns>
        public bool TryMergeModules(ExcelVbaProject sourceProject, ExcelVbaProject targetProject, out IEnumerable <ExcelVBAModule> modules)
        {
            try
            {
                ////	Get all modules, classes, and user forms from each project
                var sourceItems = sourceProject.Modules.Where(x => x.Type == eModuleType.Module || x.Type == eModuleType.Class).ToList();
                var targetItems = targetProject.Modules.Where(x => x.Type == eModuleType.Module || x.Type == eModuleType.Class || x.Type == eModuleType.Designer).ToList();

                var removeFromSource = new List <ExcelVBAModule>();
                var removeFromTarget = new List <ExcelVBAModule>();

                if (_onlyMergeUsed)
                {
                    foreach (var source in sourceItems)
                    {
                        if (!targetItems.Any(x => x.Code.Contains(source.Name)) && !sourceItems.Any(x => x.Code.Contains(source.Name)))
                        {
                            removeFromSource.Add(source);
                        }
                    }
                }

                foreach (var targetItem in targetItems)
                {
                    //	Remove early binding reference since code will be local.
                    if (targetItem.Code.Contains($"{sourceProject.Name}."))
                    {
                        targetItem.Code = targetItem.Code.Replace($"{sourceProject.Name}.", "");
                    }

                    if (targetItem.Code.Contains($"{targetProject.Name}."))
                    {
                        targetItem.Code = targetItem.Code.Replace($"{targetProject.Name}.", "");
                    }

                    //	If name and code are the same, remove it from the source so it doesn't duplicate on merge.
                    if (sourceItems.Any(x => x.Name == targetItem.Name && x.Code == targetItem.Code))
                    {
                        removeFromSource.Add(sourceItems.Single(x => x.Name == targetItem.Name));
                    }

                    //	If a module of the same name exists in both projects, but the code differs, use default or prompt user for action.
                    if (sourceItems.Any(x => x.Name == targetItem.Name && x.Code != targetItem.Code))
                    {
                        try
                        {
                            var consolePresent = Console.WindowHeight > 0;
                        }
                        catch
                        {
                            throw new ArgumentException($"The source \"{sourceProject.Name}\" and target \"{targetProject.Name}\" have a {targetItem.Type} with the same name \"{targetItem.Name}\" and different code. Please remove from one or the other and run again.");
                        }

                        ConsoleColor backColor = Console.BackgroundColor, foreColor = Console.ForegroundColor;

                        Console.BackgroundColor = ConsoleColor.Yellow;
                        Console.ForegroundColor = ConsoleColor.Black;

                        if (!_alwaysUseSource)
                        {
                            Console.WriteLine($"The source \"{sourceProject.Name}\" and target \"{targetProject.Name}\" have a {targetItem.Type} with the same name \"{targetItem.Name}\" and different code. Please advise: 0 to use source, 1 to keep target.");
                        }

                        if (_alwaysUseSource || Console.ReadLine().ToString() == "0")
                        {
                            removeFromTarget.Add(targetItem);
                        }
                        else
                        {
                            removeFromSource.Add(sourceItems.Single(x => x.Name == targetItem.Name));
                        }
                        Console.BackgroundColor = backColor;
                        Console.ForegroundColor = foreColor;
                    }
                }

                foreach (var item in removeFromTarget)
                {
                    targetItems.Remove(item);
                }

                foreach (var item in removeFromSource)
                {
                    sourceItems.Remove(item);
                }

                ////	Change the name of the source objects to contain the source's VBAProject name
                //foreach (var item in sourceItems)
                //{
                //	var name = $"{sourceProject.Name}_{item.Name}";
                //	item.Name = name;
                //}

                _logger.Log($"Merging source:\n\t{String.Join("\n\t", sourceItems.Select(x => x.Name))}\nWith Target:\n\t{String.Join("\n\t", targetItems.Select(x => x.Name))}");

                //	Put them together
                modules = targetItems.Concat(sourceItems);

                _logger.Log($"Merge complete:\n\t{String.Join("\n\t", modules.Select(x => x.Name))}");

                return(true);
            }
            catch (Exception ex)
            {
                throw;
            }
        }