1 /** 2 Interface for registering worksheet functions with Excel 3 */ 4 module xlld.worksheet; 5 6 /** 7 Simple wrapper struct for a value. Provides a type-safe way 8 of making sure positional arguments match the intended semantics, 9 which is important given that nearly all of the arguments for 10 worksheet function registration are of the same type: wstring 11 ST is short for "SmallType". 12 */ 13 private mixin template ST(string name, T = wstring) { 14 mixin(`struct ` ~ name ~ `{ T value; }`); 15 } 16 17 struct Procedure { 18 wstring value; 19 string toString() @safe pure const { 20 import std.conv: to; 21 return value.to!string; 22 } 23 } 24 25 mixin ST!"TypeText"; 26 mixin ST!"FunctionText"; 27 mixin ST!"ArgumentText"; 28 mixin ST!"MacroType"; 29 mixin ST!"Category"; 30 mixin ST!"ShortcutText"; 31 mixin ST!"HelpTopic"; 32 mixin ST!"FunctionHelp"; 33 mixin ST!("ArgumentHelp", wstring[]); 34 35 36 /** 37 The arguments used to register a worksheet function with the spreadsheet. 38 */ 39 struct WorksheetFunction { 40 // the first few parameters have to be set, the others are optional 41 Procedure procedure; 42 TypeText typeText; 43 FunctionText functionText; 44 Optional optional; 45 alias optional this; //for ease of use 46 47 /** 48 Returns an array suitable for use with spreadsheet registration 49 */ 50 const(wstring)[] toStringArray() @safe pure const nothrow { 51 return 52 [ 53 procedure.value, typeText.value, 54 functionText.value, argumentText.value, 55 macroType.value, category.value, 56 shortcutText.value, helpTopic.value, functionHelp.value 57 ] ~ argumentHelp.value; 58 } 59 } 60 61 // helper template to type-check variadic template constructor below 62 private alias toType(alias U) = typeof(U); 63 64 /** 65 Optional arguments that can be set by a function author, but don't necessarily 66 have to be. 67 */ 68 struct Optional { 69 ArgumentText argumentText; 70 MacroType macroType = MacroType("1"w); 71 Category category; 72 ShortcutText shortcutText; 73 HelpTopic helpTopic; 74 FunctionHelp functionHelp; 75 ArgumentHelp argumentHelp; 76 77 this(T...)(T args) { 78 import std.meta: staticIndexOf, staticMap, allSatisfy, AliasSeq; 79 import std.conv: text; 80 81 static assert(T.length <= this.tupleof.length, "Too many arguments for Optional/Register"); 82 83 // myTypes: ArgumentText, MacroType, ... 84 alias myTypes = staticMap!(toType, AliasSeq!(this.tupleof)); 85 enum isOneOfMyTypes(U) = staticIndexOf!(U, myTypes) != -1; 86 static assert(allSatisfy!(isOneOfMyTypes, T), 87 text("Unknown types passed to Optional/Register constructor. ", 88 "Has to be one of:\n", myTypes.stringof)); 89 90 // loop over whatever was given and set each of our members based on the 91 // type of the parameter instead of by position 92 foreach(ref member; this.tupleof) { 93 enum index = staticIndexOf!(typeof(member), T); 94 static if(index != -1) 95 member = args[index]; 96 } 97 } 98 } 99 100 /** 101 A user-facing name to use as an UDA to decorate D functions. 102 Any arguments passed to its constructor will be used to register 103 the function with the spreadsheet. 104 */ 105 alias Register = Optional; 106 107 108 struct Dispose(alias function_) { 109 alias dispose = function_; 110 }