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