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 const bool opEquals(const WorksheetFunction rhs) @safe pure { return optional == rhs.optional; } 62 } 63 64 // helper template to type-check variadic template constructor below 65 private alias toType(alias U) = typeof(U); 66 67 /** 68 Optional arguments that can be set by a function author, but don't necessarily 69 have to be. 70 */ 71 struct Optional { 72 ArgumentText argumentText; 73 MacroType macroType = MacroType("1"w); 74 Category category; 75 ShortcutText shortcutText; 76 HelpTopic helpTopic; 77 FunctionHelp functionHelp; 78 ArgumentHelp argumentHelp; 79 80 this(T...)(T args) { 81 import std.meta: staticIndexOf, staticMap, allSatisfy, AliasSeq; 82 import std.conv: text; 83 84 static assert(T.length <= this.tupleof.length, "Too many arguments for Optional/Register"); 85 86 // myTypes: ArgumentText, MacroType, ... 87 alias myTypes = staticMap!(toType, AliasSeq!(this.tupleof)); 88 enum isOneOfMyTypes(U) = staticIndexOf!(U, myTypes) != -1; 89 static assert(allSatisfy!(isOneOfMyTypes, T), 90 text("Unknown types passed to Optional/Register constructor. ", 91 "Has to be one of:\n", myTypes.stringof)); 92 93 // loop over whatever was given and set each of our members based on the 94 // type of the parameter instead of by position 95 foreach(ref member; this.tupleof) { 96 enum index = staticIndexOf!(typeof(member), T); 97 static if(index != -1) 98 member = args[index]; 99 } 100 } 101 } 102 103 /** 104 A user-facing name to use as an UDA to decorate D functions. 105 Any arguments passed to its constructor will be used to register 106 the function with the spreadsheet. 107 */ 108 alias Register = Optional; 109 alias Excel = Optional; 110 111 112 /// 113 struct Dispose(alias function_) { 114 alias dispose = function_; 115 }