Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 12/22/2019 in all areas

  1. 3 points
    This year 2020 will be one of Change and Challenge for the Claris FileMaker Community. It will require Commitment, Confidence, and Community Effort to see it to a successful conclusion. Herewith, in outline form, are some of the Challenges I foresee we will face: 1. We will need to develop a finer level of audit logging of Personally Identifiable Information (PII). Most logs currently focus on system level activity. A finer level of focus will assist in achieving compliance with various privacy requirements. Prompt response timelines for breaches will be an issue as well. 2. We will need to improve data level protection via encryption. The UI layer is insufficient for this purpose. But in the process of doing this, we must maintain system usability. 3. The practice of sending SMS text messages to mobile devices to achieve Two Factor Authentication (2FA) needs to end. It is inherently insecure, and there are better alternatives. 4. A better approach to 2FA is to adopt hardware tokens of various types. These can be made to work with the FileMaker Platform—indeed they already do so—using expanded oAuth Open ID Connect services. 5. We are going to need to adopt context—based authentication. Not just Who are you? and Are you who you say you are? But also, How do we know this? And from where are you seeking access, on what device, to what asset? This is not particularly easy to adopt; however, it can be done. 6. Mobile accessibility is due for a change. We are at the beginning of end of Wi-Fi. In 2020 we will begin to see adoption of what is called Citizens Broadband Radio Service (CBRS). This is not to be confused with the old CB Radio from the 1970’s. Adoption of CBRS is likely the beginning of Connectivity as a Service. 7. We will begin increasingly to see the containerization of applications and services, e.g. FileMaker Server. a. Unlike virtual machines, they don't need a full OS to be installed within the container. b. Once the container has been created, it can easily be deployed to different servers. From a software lifecycle perspective this is a great help, as containers can quickly be copied to create environments for development, testing, integration, and production. 8. We need to adopt processes that facilitate how data owners can assure they exercise due diligence on cloud-hosted data. The owner is the responsible party here. And it is the owner who likely would suffer the bulk of the onus of any breach. In order to exercise this due diligence, data owners must expect and insist on transparency from hosting and PaaS providers about security processes including who does and does not have access to and knowledge of encryption keys. This will not be a straightforward process. 9. As we experience more and more instances of Machine Learning, we will need to be aware of, and to guard against, manipulation of the Training Data that underpins this process. Such data are susceptible to attack and to manipulation that poisons the data. Even a very small amount of such alteration can affect the machine learning process. 10. The Human Element has always been at the center of effective FileMaker Platform Security. That will become even more the case in 2020 and beyond as we move to Federated Identity Management and to Digital Transformation. The culture of any organization is a governing element for its success. We will have many challenges here properly to account for and to plan for the Human Element. Steven H. Blackwell Platinum Member Emeritus
  2. 2 points
    The easy way to solve such problems is to: 1. Enter the "native" version of your AppleScript into a text field: display dialog "Hello \"world\" " 2. Open the Data Viewer and enter: Quote ( YourTable::Textfield ) 3. Paste the result into your calculated AppleScript formula: "display dialog \"Hello \\\"world\\\" \" "
  3. 2 points
    Here is my documentation on word break rules, taken mostly from discussions here on FMForum over the years and MOSTLY from Comment 🙂 The ampersand and hyphen are word delimiters - but they are not the only ones. There are many more, first and foremost a space, of course. I don't know if there's a comprehensive list, but at least !@%^()≠+[]{}<>≤≥`~|\? are all word delimiters. Word delimiters are not words, so you cannot get them with the MiddleWords() function. space * # ; " = $ € & / ≈ ∏ ‡ Detailed feedback: If I go to FileMaker Pro 11 Help for MiddleWords, the example uses spaces and the note refers to ampersand(&) and hyphen(-) to identify the beginning of a new word. No other symbols are given. I was curious about what other symbols might be able to be used. I created an Excel spreadsheet with the ASCII 255 characters and created text with separators using each of the characters. When I imported it into FileMaker Pro, I used MiddleWords in my calculation, I found that a period (char 46) did not work, I did find the following symbols did work: Char 9 is ", "Char 10 is ", Char 11 is , Char 12 is , " Char 13 is ", Char 32 is , Char 33 is !, Char 34 is ", Char 35 is #, Char 36 is $, Char 37 is %, Char 38 is &, Char 40 is (, Char 41 is ), Char 42 is *, Char 43 is +, Char 44 is ,, Char 45 is -, Char 47 is /, Char 58 is :, Char 59 is ;, Char 60 is <, Char 61 is =, Char 62 is >, Char 63 is ?, Char 64 is @, Char 91 is [, Char 92 is \, Char 93 is ], Char 94 is ^, Char 95 is _, Char 96 is `, Char 123 is {, Char 124 is |, Char 125 is }, Char 126 is ~, Char 128 is €, Char 130 is ‚, Char 132 is „, Char 133 is …, Char 134 is †, Char 135 is ‡, Char 136 is ˆ, Char 137 is ‰, Char 139 is ‹, Char 147 is “, Char 148 is ”, Char 149 is •, Char 150 is –, Char 151 is —, Char 152 is ˜, Char 153 is ™, Char 155 is ›, Char 161 is ¡, Char 162 is ¢, Char 163 is £, Char 164 is ¤, Char 165 is ¥, Char 166 is ¦, Char 167 is §, Char 168 is ¨, Char 169 is ©, Char 171 is «, Char 172 is ¬, Char 173 is ­, Char 174 is ®, Char 175 is ¯, Char 176 is °, Char 177 is ±, Char 180 is ´, Char 182 is ¶, Char 183 is ·, Char 184 is ¸, Char 187 is », Char 191 is ¿, Char 215 is ×, Char 247 is ÷, NOTE: The character ` acts as a word separator on the Macintosh but not in Windows. RULE 1 (period .) one.two = 1 word one.2 = 2 words 1.two = 2 words 1.2 = 1 word RULE 2 (slash / hyphen - colon : comma ,) one-two = 2 words 1-two = 2 words one-2 = 2 words 1-2 = 1 word RULE 3 (single quote ') one'two = 1 word one'2 = 2 words 1'two = 2 words 1'2 = 2 words I think it is very important information. The old links are no longer available from what I can tell, which is why I'm just posting my 'combined-gathered' rules here again.
  4. 2 points
    It depends not only on the character following the punctuation mark, but also on the character preceding it: WordCount ( "A-1" ) = 2 WordCount ( "1-1" ) = 1 And these results are not necessarily the same for all punctuation marks.
  5. 1 point
    First thing I'd check is File > Manage > External Data Sources... in your Clients file to make sure it's not pointing to some other copy of Orders. Welcome to the forums. 😎
  6. 1 point
    Try something like: "data:text/html, <img src='http://s3.amazonaws.com/photos.ecarlist.com/egWK/Z0og/ECQk/1XB9/I4Zn/vw_640.jpg' style='max-height:300px; max-width:400px;'/>" See if this helps: https://support.filemaker.com/s/article/Web-Viewer-renders-blank-in-WebDirect?language=en_US
  7. 1 point
    Create a data entry form use some global fields when you hit the button to add new invoice to the vendor you set the VendorID to a global field then have the user enter the invoice number in another global field use these fields as predicates to the invoice table and do a test to see if Count ( invoice::uuid ) ≠ 1 then it would be safe to add this invoice. The goal here is enter the values in to globals and validate before you actually create the record. alternatively you could create a concatenated field VendorID & "-" & InvoiceNo and then GlobalVendorID &"-"& GlobalInvoiceNo then relate these fields and single equal join link between them
  8. 1 point
    Careful with that, a text field behaves differently than a number field. If your users (or your scripts) are using that field for searches then searching for 1 will also yield 10, 11, 100,... And sorting will behave differently too. So if you were relying on that field acting as a number then you are better off leaving it as a number and using a 'shadow' filed as I mentioned.
  9. 1 point
    Yes, it is expected behavior. Under the hood, FM tracks most things by ID and not by name, So when you paste code (fields, scripts,...) and it has references to other objects then FM will match them up by ID, which may or may not be the field or script you intended.
  10. 1 point
    welcome to the forums a field can't have two types of style formatting applied with regard to entry - or drop down you may stack two of the same fields and use hide object when logic to hide the field based on you yes/no field.
  11. 1 point
    I hear ya. Integrating with anything comes at a cost. You can either build or buy. If you build, you bear the responsibility of keeping track of the FedEx changes, make sure you get early notifications and spend some time on those. If you buy you have to do vendor risk management: is the vendor quick to support, are in for the long haul... decisions, decisions...
  12. 1 point
    I am not sure if this is possible with plastic, you can use it with a mag stripe reader connected via USB. At this time i don't believe Plastic will work with CHIP readers or NFC readers. Some merchant terminals may have some sort of api where that device after payment capture happens you click a button on the computer that which knows the device id and your api key you do a request to there merchant api and get back a result from the recent transaction, including the payment approved amount or if it was declined etc.
  13. 1 point
    Your best bet is to use the FedEx APIs instead of xDBC. Their APIs are great and extensive, and FM happens to be really good at consuming APIs.
  14. 1 point
    Under certain assumptions (which I hope will be self-evident), you could something like: Check if the last line matches the pattern of "@@ #####"; if yes, set the Country field to USA (or leave it empty?), the State field to the first word of the last line, the ZIP field to the second word of the last line, and the City to the entire line before last . Otherwise , set the Country field to the entire last line. If the last line is "Canada", parse the line before last as follows: the last 2 words (or 7 characters) go to the ZIP field, the 3rd word from right is the State, and the rest is the City. If the last line is something else, then we don't know how to handle the line before last. Now we need to look at the remaining lines: if there are 2 remaining lines, then the first of them is Owner1 and the other one is Address 1. If there are 4 of them, then the first 2 are owners and the other two are the address. If there are 3 remaining lines, then check if the 2nd line begins with a digit character (or with a word that consist of digits only?). If yes, then there is one owner and two address lines, otherwise it's two owners and one address line. The problem with this approach is, of course, that if will fail colossally when any of these assumptions is not true, as well as the missing instructions for countries other than USA and Canada. So at best it can serve as a first draft for human review.
  15. 1 point
    Can you post a simple file showing the problem (and hopefully only the problem)? -- Note that your filtering expressions are unnecessarily convoluted. The result of a filtering expression needs to be either True or False. Your expressions return Table::ID instead of True. We don't see the contents of the Table::ID field, so we don't know what it will return when converted to a Boolean. This is probably not the cause of the problem you raise, but instead of: If ( Table::Type1 = "ABL" ; Table::ID ; 0 ) you should be using: Table::Type1 = "ABL" and likewise: If ( Table::Type1 = "ABL" and ( Table::Type2 = "XA" or Table::Type2 = "YA" or Table::Type2 = "ZA") ; Table::ID ; 0 ) should be: Table::Type1 = "ABL" and ( Table::Type2 = "XA" or Table::Type2 = "YA" or Table::Type2 = "ZA" )
  16. 1 point
    Better write a template than a for-each
  17. 1 point
    IMHO you should import each language as a separate record (otherwise why would you need the language field). So the first 5 fields you show should be quite sufficient. However, you will need another field to link the multiple records to a common parent citation. I don't see a unique identifier in the provided XML example, and this might pose a problem - esp. if the source can contain multiple citations. Note that this assumes that the labels (OBJECTIVE, METHOD, RESULTS, CONCLUSIONS) are always the same (even if some are missing). Otherwise the proper structure for importing such data is to have a record for each AbstractText, with fields for: CitationID Label Language AbstractText
  18. 1 point
    Not sure where you get this impression from. See if the attached demo works for you. HighlightSimilar.fmp12
  19. 1 point
    Enter this into FileMaker's calculation dialog ( in the 'Calculated AppleScript' dialog ). "display dialog \"Hello \\\"world\\\"\"" " - opening quote required for text in FileMaker display dialog - applescript command \" - escaped quote mark reduces to a " when evaluated by FileMaker. Hello - the string to appear inside the quoted string being fed to the AppleScript. \\ - an escaped backward slash, that reduces to a single backward slash when evaluated by FileMaker. \" - an escaped quote, that pairs with the previous backward slash, to open the string to pass to the AppleScript command. world - string for inside the escaped quotes to feed into AppleScript. \\ - an escaped backward slash, that reduces to a single backward slash when evaluated by FileMaker. \" - an escaped quotation mark, that pairs with the previous backward slash, to form an escaped quotation mark to pass to AppleScript. \" - another escaped quotation mark to close the string to pass into the AppleScript command. " - closing quote required for text in FileMaker. Visually it looks like this ( red characters reduce down when evaluated in FileMaker 😞 "display dialog \"Hello \\\"world\\\"\""
  20. 1 point
    The pattern: X-17 is two words. When you search for: X*17* Filemaker looks for a single word that starts with "X" and contains "17", e.g. "xy217z".
  21. 1 point
    Keep in mind that there are two FM Clouds. The "for AWS" is the old 1.0 and that one does support special Linux versions of plugins. But the new FM Cloud (2.0) does not support plugins.
  22. 1 point
    You could use a calculation = Max ( Max ( ChildTableA::Datefield ) ; Max ( ChildTableB::Datefield ) ; Max ( ChildTableC::Datefield ) ) However, if you have 3 child tables that are alike in that you need to know the latest date in all three, then maybe they should be consolidated into one.
  23. 1 point
    Well, I suggest you put some restriction on the number of allowed values, because otherwise this gets (even more) complicated. Some background: Your question is a variation of the subset sum problem, which in turn is a special case of the knapsack problem. Both are VERY difficult problems to solve programatically. Even worse, the known solutions are difficult to implement in Filemaker, because its calculation engine has no arrays. Fortunately, with a small number of values, a naive brute-force solution is feasible: enumerate all possible combinations of the given values, calculate the sum of each combination, and compare it to the target sum. The attached demo is designed to deal with up to 7 values. It has 127 records to enumerate the 2^7 -1 = 127 possible combinations, and a repeating calculation field with 7 repetitions to list the values of each combination. You can extend the limit by adding more records and more repetitions, but - as I said - this is a brute-force approach and it will get slower as the number of values increases. SubsetSum.fmp12
  24. 1 point
    Adding Preferences (via the iOS Settings App) to a FIAS project How to create and utilize native iOS Preferences functionality (in the Apple-provided Settings App) and share those preferences with the FIAS solution database, using the AppDelegate in a FileMaker iOS App SDK (FIAS) project (v18). What You'll Learn How to add native App Settings functionality to a FIAS project in Xcode. How to share/pass the App Settings data with the FIAS solution database. What This Post Is Not A tutorial on FIAS A tutorial on Xcode A tutorial on Objective-C Requirements iOS App SDK 18+ (not tested on v17, but may work just fine) Xcode 10+ What We're Going To Do Add an Objective-C App Delegate class Verify the App Delegate class Implement App Delegate Methods to communicate with FileMaker database Add a 'Settings bundle' file that defines the preferences to display Verify the Settings data is accessible by the App Delegate Verify the Settings data can be shared with a FileMaker script Your FIAS Project Either open up and existing FIAS project or create a new one. Make sure you can build it and run it, either in the iOS Simulator or on your own device. Xcode: Add an Objective-C App Delegate class Bring up your existing App Delegate class in the Xcode editor or create a New File, using the file type 'Objective-C File' as the document type. Be sure to save this new file into your existing 'Custom Application Resources' directory. Note: If you are adding this App Delegate class to your project for the first time, be sure to follow the instructions in the iOS SDK Documentation for modifying the 'configFile.txt' file so that applicationDelegateClass = MyAppDelegate Use the following code in your App Delegate file as a starting point. #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "FMX_Exports.h" #define kUserNameKey @"username_preference" #define kPasswordKey @"password_preference" #define kDatasourceKey @"datasource_preference" @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { } @property (strong, nonatomic) UIWindow *window; @end @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); return true; } @end Verify the App Delegate Class Build the project (Command-B). You shouldn't have any errors. Run the project (Command-R). When it runs the console should display the NSLog string from inside the function 'didFinishLaunchingWithOptions': MyAppDelegate: -[MyAppDelegate application:didFinishLaunchingWithOptions:] Note: to show the Console, type Command + Shift + c FileMaker: Create a FileMaker Script Open your FIAS database locally in FileMaker Pro. Create a new Script, using any naming convention you wish. For the following examples we will use the script name 'AppDelegate_didFinishLaunchingWithOptions'. #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param; Default Button: "Excellent", Commit: “Yes” ] Close the database in FileMaker Pro and return to Xcode. Xcode: Trigger the FileMaker Script in your FIAS project Modify your existing AppDelegate file to match the following, replacing with the actual name of your database filename, not including the extension '.fmp12': - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"AppDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"A script param from Xcode", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Failed"); } return true; } Build and run the project. When it runs the console should display the 2 NSLog entries from inside the function 'didFinishLaunchingWithOptions': MyAppDelegate: -[MyAppDelegate application:didFinishLaunchingWithOptions:] MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed Notice: the script failed to be triggered. How? What? Why? Create a NSTimer Class Object To Fix Our Script Issue I won't pretend to know the answer as to why this failed, but I can provide an educated guess. The FileMaker framework handles all of the UIWindow, UIViewController, and UIView pieces and parts. This all takes time. My assumption is that when this function is triggered in our AppDelegate, the FileMaker database is not yet quite ready to receive and run our script request, so it quietly fails. Going on this assumption, I decided to play around with adding a slight delay in our code to see if that might solve this dilemma. It does solve it, but is not the best solution. The reason I mention this is because you will notice slight differences with the length of delay required to successfully fire off this script request, between trying this solution on the iOS Simulator and actual iOS devices (iPhones and iPads). But let's give it a try to see what your experience is in your environment. Modify your existing AppDelegate methods to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"AppDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"A script param from Xcode", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Failed"); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); NSLog(@"didFinishLaunchingWithOptions: creating a timer to launch script 'AppDelegate_didFinishLaunchingWithOptions'"); // FIAS needs a little time to begin responding to script requests, so add a slight delay // simulator is fairly quick (2 seconds works fine) but iOS device seems to take longer, at least with debugger, needing 10 seconds [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; return true; } Build and run the project. When it runs the console should display the 2 NSLog entries from inside the function 'didFinishLaunchingWithOptions': If it runs successfully you will see the success message in the Console and you will also see the Custom Dialog appear in your App, that you added previously in your Script. You should also see that your Script Parameter was successfully passed to the Script. didFinishLaunching script If it still did not trigger successfully, try increasing the TimeInterval value from 2.0 to 4.0, or 6.0, or whatever you want to try , in order to determine the sweet spot of a small enough value to work every time. My own experience has resulted in a 2.0 second delay for the Simulator and a 10.0 second delay in my iPhone XSMax running on iOS v13 beta. If it still does not trigger, or if the Console shows that it triggered successfully, but your App does not present the expected Custom Dialog, be sure to refer back to the iOS SDK installation instructions regarding copying the solution file (database) into the iOS project. This is a setting you can adjust in the configFile.txt file. During development I would recommend selecting always so that it copies the database every time you run the project. Xcode: Optional Additional AppDelegate Script Trigger Methods All of the following code is optional. You can pick and choose which ones to add to your project. Most, if not all of these, will not need a NSTimer delay in order to successfully trigger a FileMaker Script to be run. I would highly recommend having each and every additional FileMaker Script that you add for any of these methods to contain a ShowCustomDialogscript step so that you can get a feel for how each of these methods actually perform while the User is using your App. For instance, the method didChangeStatusBarOrientation seems to be triggered twice in succession for every single time it is triggered by the OS. This is the type of scenario you need to be aware of ahead of time while you develop your project, so that you can plan your process flow accordingly. - (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidBecomeActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidBecomeActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidBecomeActive Failed"); } } - (void)completedReturnToForegroundActive { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_completedReturnToForegroundActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_completedReturnToForegroundActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_completedReturnToForegroundActive Failed"); } } - (void)applicationWillTerminate:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillTerminate", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillTerminate Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillTerminate Failed"); } } - (void)applicationWillResignActive:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillResignActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillResignActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillResignActive Failed"); } } - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidEnterBackground", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidEnterBackground Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidEnterBackground Failed"); } } - (void)applicationWillEnterForeground:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillEnterForeground", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillEnterForeground Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillEnterForeground Failed"); } } - (void)applicationSignificantTimeChange:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationSignificantTimeChange", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationSignificantTimeChange Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationSignificantTimeChange Failed"); } } - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidReceiveMemoryWarning", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidReceiveMemoryWarning Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidReceiveMemoryWarning Failed"); } } - (void)application:(UIApplication *)application didChangeStatusBarOrientation: (UIInterfaceOrientation)oldStatusBarOrientation { // seems to trigger twice every time NSLog(@"MyAppDelegate: %s Calling FMX_Queue_Script appDelegate_didChangeStatusBarOrientation", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didChangeStatusBarOrientation", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didChangeStatusBarOrientation Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didChangeStatusBarOrientation Failed"); } } Passing Multiple Script Parameters Sometimes you want to pass multiple script parameters to a script, and the SDK has a very nice and easy process for doing so. Modify your existing AppDelegate methods to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); NSDictionary<NSString *, NSString *> *variables = @ { @"$a": @"Value of $a", @"$z": @"Value of $z" }; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"ima script param", variables)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s Calling FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions", __func__); // FIAS needs a little time to begin responding to script requests, so add a slight delay [NSTimer scheduledTimerWithTimeInterval: 10.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; return true; } Now modify your existing FileMaker Script AppDelegate_didFinishLaunchingWithOptions to match the following: #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param & "¶" & "sdk_$a: " & $a & "¶" & "sdk_$z: " & $z Default Button: "Excellent", Commit: “Yes” ] Build and run the project. When it runs you should see a Custom Dialog confirming that these 2 variables were successfully passed into your Script. I have not tested this, but this code snippet leads me to believe that many multiple parameters can be passed into a FileMaker Script by simply following the code structure and syntax of the NSDictionary object we just added. I have no idea how many or what limits there are, but I would suppose that you would be able to pass in just about whatever you desire to pass in and it would just work. As an example, here would be the adjustment to that NSDictionary code in order to pass in 4 additional parameters, instead of the 2 we passed earlier: NSDictionary<NSString *, NSString *> *variables = @ { @"$a": @"Value of $a", @"$z": @"Value of $z", @"$anotherCoolScriptParameter": @"$1,234,567.99", @"$dontForgetAboutMeParameter": @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tincidunt hendrerit tellus, id vestibulum odio venenatis et. Integer arcu est, efficitur sed cursus vitae, efficitur quis nisl." }; The iOS Settings App First off, here is a quote from Apple's Human Interface Guidelines, regarding the Settings App and it's intended purpose: So, with that in mind, let us create a file (called Settings.bundle) that will be automatically installed by Xcode, that will generate our own custom settings into the Settings.app. Then later we will add code to interact with the data our Users will enter into the Settings.app. Create a New File from the File menu, select Settings Bundle from the iOS Resource section, leave the default filename as Settings.bundle, and be sure to select Custom Application Resources in the Group drop-down menu of your project. Look for your newly created file in the left pane of Xcode (Project navigator) and click the disclosure arrow on the left side of the filename to expand it's contents. You should see 2 items: a folder titled en.lproj and a file named Root.plist. Right-click on the file Root.plist and select OpenAs->SourceCode. Note: once you have created this file using the XML Source Code editor, you can go back and look at this same code in the Property List editor. It can be a bit tricky adding these various fields, dividers, sections, etc. in the Property List editor, so in this guide I will just have you copy and paste the complete code block in the easier Source Code editor. Replace the code with the following: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PreferenceSpecifiers</key> <array> <dict> <key>Title</key> <string>Access Credientials</string> <key>Type</key> <string>PSGroupSpecifier</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>UserName</string> <key>Key</key> <string>username_preference</string> <key>KeyboardType</key> <string>Alphabet</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>Password</string> <key>Key</key> <string>password_preference</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> <dict> <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Datasource</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>URL</string> <key>Key</key> <string>datasource_preference</string> <key>KeyboardType</key> <string>Alphabet</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> </array> <key>StringsTable</key> <string>Root</string> </dict> </plist> Run the Project. Nothing will look different at this stage. Now Quit the App, either in the Simulator or on the device. Find the Settings.app and Open it. Scroll down to the bottom of the list of Settings, and you should now see your App listed. Tap on your App. Custom App Settings And look at that, several fields for you to enter Settings, or Preferences, or whatever you wish to have the User enter in this Settings.app. Now if you go back to Xcode and look at the Root.plist file using the Property List editor, and expand all the disclosure arrows, you should see the required format for creating whatever fields you desire to use. The field option that is key to Xcode being able to communicate with these fields is labeled Identifier. Whatever you enter into this Identifierfield is the name of the variable you will use to pass the user-entered data into your code, and eventually into FileMaker as a parameter. Settings.bundle Root.plist Extracting the Settings.app User Data Into Xcode AppDelegate Modify your existing AppDelegate code (the interface section near the top of the file) to match the following: @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { NSString *settingsUsername; NSString *settingsPassword; NSString *settingsDatasource; } @property (strong, nonatomic) UIWindow *window; @end Then modify your existing triggerScript_didFinishLaunchingWithOptions method to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); if (settingsUsername == nil) { settingsUsername = @""; } if (settingsPassword == nil) { settingsPassword = @""; } if (settingsDatasource == nil) { settingsDatasource = @"<invalid>"; } NSDictionary<NSString *, NSString *> *variables = @ { @"$username": settingsUsername, @"$password": settingsPassword }; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, settingsDatasource, variables)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } Now modify your didFinishLaunchingWithOptions method to match the following: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); // FIAS needs a little time to begin responding to script requests, so add a slight delay [NSTimer scheduledTimerWithTimeInterval: 10.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; // Pulling data from Settings NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; settingsUsername = [defaults objectForKey:kUserNameKey]; settingsPassword = [defaults objectForKey:kPasswordKey]; settingsDatasource = [defaults objectForKey:kDatasourceKey]; NSLog(@"MyAppDelegate - standardUserDefaults - username: %@", settingsUsername); NSLog(@"MyAppDelegate - standardUserDefaults - password: %@", settingsPassword); NSLog(@"MyAppDelegate - standardUserDefaults - datasource: %@", settingsDatasource); return true; } Then modify your FileMaker Script AppDelegate_didFinishLaunchingWithOptions to match the following: #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param & "¶" & "sdk_$username: " & $username & "¶" & "sdk_$password: " & $password Default Button: "Excellent", Commit: “Yes” ] Before running your app, go back into the Settings.app and enter in some random values into those 3 fields so that they are not blank. Then close the Settings.app and return to Xcode. Now Run your project. If all went well you should have seen the user-entered Settings values show up in the Console and inside the Custom Dialog in the App itself. Conclusion You now should have completed what we set out to do. There are several ways you can customize these examples to match what you would like to do in your own app. Hopefully this has been a helpful and in-depth guide on putting the AppDelegate to work for you in a useful and meaningful way. Happy FileMaking. Further Reading You can read more about the various AppDelegate Methods here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate A Future Feature Request It would be great to have a way to communicate between the database solution file and the AppDelegate Methods. Maybe with a pre-determined standard global variable; something like $$SDK.SHARED.DATA. I'm not sure what everyone would use it for, but here is an idea I have come up with for helping to solve to delay issue we dealt with earlier in this project. Instead of statically creating a delay of 2.0 - 10.0 seconds, it would be a much better solution to create a loop in the Delegate code, maybe with a 0.5 - 1.0 second delay between iterations, to check for the existence of a certain value in this proposed global variable. For example: @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { NSTimer *myTimer; NSString *sdk_shared_data; } @property (strong, nonatomic) UIWindow *window; @end @implementation MyAppDelegate - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSString *fmpVariable = sdk_shared_data; if ([fmpVariable isEqual: @"helloFromFileMakerGlobalVariable"]) { [myTimer invalidate]; myTimer = nil; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"none", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: YES]; return true; }
  25. 1 point
    Quick devcon preview to show the power of Zabbix to monitor but also correct your FileMaker Server: https://www.soliantconsulting.com/blog/filemaker-server-zabbix/
  26. 1 point
    Ah, you're right. I usually use enter find mode and set fields. With perform find you'd have to create a single variable that holds from and to date, and use that single var in the perform find. Like so: set variable[ $daterange; $start & "..." & $end ] Perform Find [ Specified Find Requests: Find Records; Criteria: Log::Date: $daterange ] [ Restore ] 
  27. 1 point
    Try the following stylesheet: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/PubmedArticleSet"> <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult"> <METADATA> <FIELD NAME="PubmedID"/> <FIELD NAME="PiiID"/> <FIELD NAME="DoiID"/> <FIELD NAME="PmcID"/> </METADATA> <RESULTSET> <xsl:for-each select="PubmedArticle"> <ROW> <COL><DATA><xsl:value-of select="PubmedData/ArticleIdList/ArticleId[@IdType='pubmed']"/></DATA></COL> <COL><DATA><xsl:value-of select="PubmedData/ArticleIdList/ArticleId[@IdType='pii']"/></DATA></COL> <COL><DATA><xsl:value-of select="PubmedData/ArticleIdList/ArticleId[@IdType='doi']"/></DATA></COL> <COL><DATA><xsl:value-of select="PubmedData/ArticleIdList/ArticleId[@IdType='pmc']"/></DATA></COL> </ROW> </xsl:for-each> </RESULTSET> </FMPXMLRESULT> </xsl:template> </xsl:stylesheet> This will present four source fields to the Filemaker's import dialog. Of course, you will also need to have four corresponding target fields in your solution, so that you can map the imported data to them. Indeed, the DOCTYPE declaration is causing a problem. I am not quite sure why - I suspect it's an OS permissions issue that comes up when the XSLT engine tries to access the online DTD document.
  28. 1 point
    Then again they have two options: 1. Define a calculation field = If ( Status = "Verified" ; TransactionID ) and define the value list to use values from this field; 2. Use a relationship to filter only verified transactions, and define the value list to include only related values from this relationship. The exact details depend on where they need this value list (and in most cases there will be more than one way to set this up).
  29. 1 point
    If you select multiple objects and apply conditional formatting, they will all get the CF option you just entered. This will remove any prior CF applied to all the objects, though.
This leaderboard is set to Los Angeles/GMT-08:00
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.