Esempio n. 1
0
        private static IScript <Globals> CreateScript(XlScriptOptions xlScriptOptions)
        {
            var options = CreateScriptingOptionsFrom(xlScriptOptions);
            var script  = m_ScriptFactory.Create <Globals>(m_GlobalsFactory, options);

            return(script);
        }
Esempio n. 2
0
        public static object OptionsCreate(
            [ExcelArgument(Description = "Name of the object handle to be created")] string HandleName,
            [ExcelArgument(Description = "Return type of the script. Object by default.")] string ReturnType = "object",
            [ExcelArgument(Description = "Hosting type for script execution. Possible values: Shared = Same for all scripts (default). Individual = Seperate AppDomain for each script. Global = Same AppDomain as ExcelScript-Addin.")] string HostingType = "Shared"
            )
        {
            Type _ReturnType = ToType(ReturnType);

            ScriptingAbstractions.HostingType _HostingType = ToHostingType(HostingType);

            var options = new XlScriptOptions(_ReturnType, _HostingType);

            return(AddOrUpdateInStoreOrThrow <XlScriptOptions>(HandleName, options, () => TryDispose(options)));
        }
Esempio n. 3
0
        private static ScriptingOptions CreateScriptingOptionsFrom(XlScriptOptions xlScriptOptions)
        {
            var options = new ScriptingOptions();

            foreach (var reference in GetScriptDefaultReferences())
            {
                options.References.Add(reference);
            }

            foreach (var import in GetScriptDefaultImports())
            {
                options.Imports.Add(import);
            }

            options.HostingType = xlScriptOptions.HostingType;

            return(options);
        }
Esempio n. 4
0
        public static object Create(
            [ExcelArgument("Name for a handle under which the script object will be stored in memory")] string HandleName,
            [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
            [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
            [ExcelArgument("An arbitrary number of handles to parameter definitions (as created by ExcelScript.Parameters.Create), which define input parameters for the script")] params string[] ParameterHandles)
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }

            string _code = String.Join(Environment.NewLine, code);

            // Get Options
            XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow <XlScriptOptions>(OptionsHandle);

            // Create Script object
            var script = CreateScript(xlScriptOptions);

            script.Code       = _code;
            script.ReturnType = xlScriptOptions.ReturnType;

            foreach (var parameterHandle in ParameterHandles)
            {
                var        parameterHandleName = HandleNames.GetNameFrom(parameterHandle);
                IParameter storedParameter     = GetFromStoreOrThrow <IParameter>(parameterHandleName);
                script.Parameters.Add(storedParameter);
            }

            IStoredObject <IScript> storedScript;

            if (m_ObjectStore.GetByName <IScript>(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
            {
                return(HandleNames.ToHandle(storedScript));
            }
            else
            {
                return(AddOrUpdateInStoreOrThrow <IScript>(HandleName, script, () => TryDispose(script)));
            }
        }
Esempio n. 5
0
        public static object Parse(
            [ExcelArgument("The code for this script. Multiple lines are allowed.")] string[] code,
            [ExcelArgument("A handle to script option definitions as created by ExcelScript.Options.Create. Can be left blank to use defaults.")] string OptionsHandle = "",
            [ExcelArgument("Name for a handle under which the script object will be stored in memory, Can be ommitted, in which case the function name will be used.")] string HandleName = "")
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }

            string _code = String.Join(Environment.NewLine, code);

            // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
            Func <MethodInfo[], MethodInfo> EntryMethodSelector = (methods) =>
            {
                var        _DEBUG_APPD = AppDomain.CurrentDomain.Id;
                MethodInfo result      = null;

                // When only one method is available, we'll just return that one...
                if (methods.Count() == 1)
                {
                    result = methods.Single();
                }
                else
                {
                    // Otherwise, we'll try to find a (one) function marked with an [ExcelFunction] attribute
                    var markedMethods = methods
                                        .Where(x => x.GetCustomAttribute <ExcelFunctionAttribute>() != null);

                    if (markedMethods.Count() == 0)
                    {
                        throw new ArgumentException($"Your script defines {methods.Count()} methods; please mark one of them with the [ExcelFunction] attribute, to mark which function shall be used as an entry point to your script.");
                    }

                    if (markedMethods.Count() > 1)
                    {
                        throw new ArgumentException($"Please only mark one function with an [ExcelFunction] attribute; you have currently marked {markedMethods.Count()} functions: " + String.Join(", ", markedMethods.Select(x => x.Name)));
                    }

                    result = markedMethods.Single();
                }

                return(result);
            };

            // CAREFUL: This method may be run in a different AppDomain! Don't reference anything from outside of the delegate
            Func <MethodInfo, IParameter[]> EntryMethodParameterFactory = (method =>
            {
                return(method
                       .GetParameters()
                       .Select(x =>
                {
                    var excelArgumentAttribute = x.GetCustomAttribute <ExcelArgumentAttribute>();

                    return new Parameter
                    {
                        Name = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Name)) ? x.Name : excelArgumentAttribute.Name,
                        Type = x.ParameterType,
                        IsOptional = x.IsOptional,
                        DefaultValue = x.DefaultValue,
                        Description = (excelArgumentAttribute == null || String.IsNullOrWhiteSpace(excelArgumentAttribute.Description)) ? String.Empty : excelArgumentAttribute.Description
                    };
                })
                       .ToArray());
            });

            // Create Script object
            XlScriptOptions xlScriptOptions = (String.IsNullOrEmpty(OptionsHandle)) ? XlScriptOptions.Default : GetFromStoreOrThrow <XlScriptOptions>(OptionsHandle);
            var             options         = CreateScriptingOptionsFrom(xlScriptOptions);

            options.References.Add(typeof(ExcelFunctionAttribute).Assembly);
            options.Imports.Add(typeof(ExcelFunctionAttribute).Namespace);

            var parseResult = m_ScriptFactory.ParseFromAsync <Globals>(m_GlobalsFactory, options, _code, EntryMethodSelector, EntryMethodParameterFactory).Result;
            var script      = parseResult.Script;

            script.ReturnType = xlScriptOptions.ReturnType;

            if (String.IsNullOrWhiteSpace(HandleName))
            {
                HandleName = parseResult.EntryMethodName;
            }

            IStoredObject <IScript> storedScript;

            if (m_ObjectStore.GetByName <IScript>(HandleName, out storedScript) && storedScript.Object.GetHashCode() == script.GetHashCode())
            {
                return(HandleNames.ToHandle(storedScript));
            }
            else
            {
                return(AddOrUpdateInStoreOrThrow <IScript>(HandleName, script, () => TryDispose(script)));
            }
        }
Esempio n. 6
0
        public static object FormatCode(
            [ExcelArgument(AllowReference = true, Description = "A cell reference to the range containing C# code")] object excelRef)
        {
            Excel.Range cellRef = ToRange((ExcelReference)excelRef);

            if (cellRef == null)
            {
                throw new ArgumentException("Input was not an excel reference", nameof(excelRef));
            }

            if (cellRef.Columns.Count != 1)
            {
                throw new ArgumentException("The range must have exactly one column", nameof(excelRef));
            }

            IEnumerable <string> codeLines = cellRef.Cells.Select(x => Convert.ToString(x.Value));

            // Remove all empty lines at the beginning and end
            codeLines = codeLines.SkipWhile(x => String.IsNullOrWhiteSpace(x))
                        .Reverse()
                        .SkipWhile(x => String.IsNullOrWhiteSpace(x))
                        .Reverse();

            var code = String.Join(Environment.NewLine, codeLines);

            XlScriptOptions xlScriptOptions = XlScriptOptions.Default;
            var             options         = CreateScriptingOptionsFrom(xlScriptOptions);

            var formattedCode = Script <Globals> .GetFormattedCodeAsync(code, options).Result;

            if (formattedCode.TextLines.Count > cellRef.Rows.Count)
            {
                throw new ArgumentException($"The formatted result has {formattedCode.TextLines.Count} lines, but the input range has only {cellRef.Rows.Count}; please expant your input range.", nameof(excelRef));
            }

            for (int i = 0; i < cellRef.Rows.Count; i++)
            {
                Excel.Range target = cellRef[i + 1, 1];

                if (i >= formattedCode.TextLines.Count)
                {
                    // The target range is bigger than what we need; just clear out the unused cells
                    target.ClearContents();
                }
                else
                {
                    var line = formattedCode.TextLines.ElementAt(i);
                    target.Value = line.Text;

                    foreach (var linePart in line.Parts)
                    {
                        var characters = target.Characters(linePart.LineSpan.Start + 1, linePart.LineSpan.Length);
                        var textColor  = linePart.TextFormat.TextColor;
                        var excelColor = Color.FromArgb(textColor.B, textColor.G, textColor.R);  // excel uses BGR format, so we convert RGB to BGR here
                        characters.Font.Color = excelColor.ToArgb();
                    }
                }
            }

            return($"({DateTime.Now.ToShortTimeString()}) Formatted");
        }