Filemaker value validation against value list - filemaker

Need to validate values within a field against Value List, retaining the value if on list but substituting a specific Value if not?

I am afraid you are mixing two separate things:
Validation checks if some conditions have been satisfied; if not, it throws an error. It will not correct the entry.
If you want user entry to be corrected, you need to either:
define the field to auto-enter a calculated value; or
attach a script trigger to it, and have the script modify the value entered by the user.
In this case, you could auto-enter a calculated value (replacing existing value) =
If ( IsEmpty ( FilterValues ( Self ; ValueListItems ( Get (FileName) ; "YourValueList" ) ) ) ; "Specific Value" ; Self )
--- Added in response to your clarification ---
Technically, you could run a script to find the records you want to verify and do Replace Field Contents (using the same calculation) on that field. You could run the script after changing the value list, as part of the weekly routine.
However, there are two major problems with this approach:
some records could be locked by another user;
you have no history of what happened, and no way to go back in case of making a mistake.
I also don't think it's good practice to have users modify a value list routinely. If you need to have a weekly list of values, you should store them in records, not in a value list. That way at least the part of the value list would have a history.
Another option you may consider is using an unstored calculation field with a similar formula. This would change dynamically with the value list, and leave the original field unmodified. This would be a good arrangement if, for example, you need to export the corrected values every week.

Related

PowerShell script to update SharePoint Online list items does not save all column values

I'm processing a CSV file to create SharePoint Online list items and save metadata as fields in its custom content type. At first, I thought it would be an issue related to column type, but I'm failing to save some simple text field values. What's puzzling is that I am able to save some but not other fields - even though I'm using the same means to do this - somehow the list item is not preserving all the values I send in for the list item update.
I create a new item with the following code:
$newFile = $targetfolderObj.Files.Add($FileCreationInfo)
$targetContext.Load($newFile)
$spContext.ExecuteQuery()
Then I get the list item and start setting the field values
$newFileListItem = $newFile.ListItemAllFields
$newFileListItem.Properties["ColumnNameA"] = $_.CustomValue1 # saves
$newFileListItem.Properties["ColumnNameB"] = $_.CustomValue2 # not saving !!!
$newFileListItem.Properties["ColumnNameC"] = $_.CustomValue3 # saves
After setting up the properties with values I call the update and execute functions.
$newFileListItem.Update()
$spContext.ExecuteQuery()
$.CustomValue1 $.CustomValue2 and $_.CustomValue3 when printed all read as "Hello" for example, there are no special characters or symbols here - even hardcoding the field values to simple strings will fail to update field 2 but works on 1 and 3.
I am giving this example with my code to show it's not sequential - for example field 2 data is NOT saved but field 1 and 3 data is saved.
It always fails on the same columns, I verified the columns exist, I'm using the internal field names, string length is well within range, and there is no other validation applied on these columns. What could I possibly do to troubleshoot this?
After a lot of debugging, I'm seeing SharePoint funnery at play...
while the content type is there, and the content type internal field name is "ColumnNameA" something must have gone sideways in the library instance, causing the column name to now be "ColumnNameA0" yes, a zero added at the end of the column name. Every column that was not updating had somehow now a "zero" at the end of the internal column name.
Solution 1: add the zero
Solution 2: recreate the library and re-associate it with the site conten type
I went with Solution 1 to test that my updates worked, then rebuilt the library.

Copy value from another table from a group footer

I'm using LL 25, trying to store a value from one table into a variable and then display it in a column in another table.
The values I need to store are being output as group footers.
Is this possible with User Variables or similar?
You can use the GetVar and SetVar functions for this purpose, as long as the value is first stored and then retrieved (i.e. the table referencing the value is printed after the table containing the value).
A simple SetVar("MyVariable", [ValueToStore]) is all it takes to store the value. Then use GetVar("MyVariable") to retrieve it later.
If the order is reversed, i.e. the table containing the variable is printed after the reference, you need to use a multi pass approach. I blogged about this very topic here:
Finally – a Glance in the Crystal Ball
This feature (i.e. the double pass) is available since version 26.GetVar and SetVar are available in 25 as well.
For older versions, the value can be precalculated and passed as variable/field.

Keeping two fields in sync when one of them is updated

The application I'm working on is a character based application. there is a field adfc.unme-code in a table and another field arbu.unit-code-shu. These two fields are shown in different windows but they must be in sync. When I update unme-code, unit-code-shu must be updated too.
Is a simple assign statement would be enough or should I do something else? Also, should I use the actual fields or a buffer?
You can use the ASSIGN statement in your code to assign both values at the same time. If there's a possibility of some other process changing those fields, you can create a database trigger procedures on each field to copy the value over to the other field. In the Data Dictionary, view the field properties and click on the "Triggers..." button to do that.
Yes, ASSIGN is used to set the value of a buffers/records field. However: certain critera needs to be met:
The buffer/record needs to be available.
You must have the "lock" of the buffer/record.
If you have the record available and locked you can simply do:
ASSIGN arbu.unit-code-shu = adfc.unme-code.
To make this code "safer" you can simply make sure that arbu is available and not locked by any other user. And finally it will handle if your assign fails because you have no lock at all.
IF AVAILABLE arbu AND NOT LOCKED arbu THEN DO:
ASSIGN arbu.unit-code-shu = adfc.unme-code NO-ERROR.
IF ERROR-STATUS:GET-NUMBER(1) = 396 THEN DO:
MESSAGE "Apparently the record is locked." VIEW-AS ALERT-BOX ERROR.
END.
END.
If you do not have the record (or the right locking) you need to look into your application and see how you can add this feature. What identifies the right record of the second table? A single id? Something else? Are there always a 1 to 1 relation between arbu and adfc etc?
Perhaps your application has a simple way of setting the value of a field. If there is a architecture at place you should try to stick to it...

How can I (partially) automate the transfer of a FileMaker database structure and field contents to a second database?

I'm trying to copy some field values to a duplicate database. One record at a time. This is used for history and so I can delete some records in the original database to keep it fast.
I don't want to manually save the values in a variable because there are hundreds of fields. So I want to go to the first field, save the field name and value and then go over to the other database and save the data. Then run a 'Go to Next Field' and loop through all the fields.
This works perfectly, but here is the problem: When a field is a calculation you cannot tab into it and therefore 'Go to Next Field' doesn't work. It skips it.
I though of doing a 'Go to Object' but then I need to name all the objects and I can't find a script to name objects.
Can anyone out there think of a solution?
Thanks!
This is one of those problems where I always found it easier to do an export/import.
Export all the data you want from the one database, and then import it into the other database. All you need to do is:
Manually specify which fields you want to copy
Map the data from the export to the right fields in the new database/table
You can even write a script to do these things for you.
There are several ways to achieve this.
To make a "history file", I have found there are several cases out there, so lets take a look.
CASE ONE
Single file I just want to "keep" a very large file with historical data, because I need to erease all data in my Main file.
In this case, you should create a "clone" table (in the same file ore in other file, is the same). Then change any calculation field to the type of the calculation result (number, text, date, an so on...). Remove any "auto entered value or calculation from any field, like auto number, auto creation date, etc..). You will have a "Plain Table" with no calculations or auto entered data.
Then add a field to control duplicate data. If you have lets say an invoice number (unique) for each record, you can do this to achieve this task. But if you do not have a unique field that identifies the record as unique, then you have to create one...
To create such a field, I recommed to add a new field on the clone table and set as an aunto entered calculation and make a field combination that is unique... somthing like this: invoiceNumber & "-" & lineNumber & "-" " & date.
On the clone table make shure that validation is set up for "always", and no empty values allowed and that this value is unique.
Once you setup the clone table... then you can import your records, making sure that the auto enty option is on. Yo can do it as many times as you like, new records will be added and no duplicates.
If you want, can make a Script to do the move to historical table all the current records before deleting them.
NOTE:
This technique works fine when the data you try to keep do not have changes over time. This means, once the record is created is has no changes.
CASE TWO
A historical table must be created but some fields are updated.
In the beginnig I thougth a historical data, never changes. In some cases I found this is not the case, like the case I want to track historical invoices but at the same time, keep track if they are paid or not...
In this case you may use the same technique above, but instead of importing data... you must update data based on the "unique" fields that identifiy the record.
Hope this technique helps
FileMaker's FieldNames() function, along with GetField() can give you a list of field names and then their values

Create a new FileMaker layout showing unique records based on one field and a count for each

I have a table like this:
Application,Program,UsedObject
It can have data like this:
A,P1,ZZ
A,P1,BB
A,P2,CC
B,F1,KK
I'd like to create a layout to show:
Application,# of Programs
A,2
B,1
The point is to count the distinct programs.
For the life of me I can't make this work in FileMaker. I've created a summary field to count programs resetting after each group, but because it doesn't eliminate the duplicate programs I get:
A,3
B,1
Any help much appreciated.
Create a a summary field as:
cntApplicaiton = Count of Application
Do this by going into define fields, create a field called cntApplication, type summary. In the options dialogue make the summary field a count on application
Now create a new layout with a subsummary part and nobody. The subsummary should be sorted on Application. Put the Application and cntApplication fields in subsummary. If you enter browse mode and sort by Application you ought to get the data you want.
You can also create a calc field with the formula
GetSummary(cntApplication; Application)
This will allow you to use the total number of Applications with in a record
Since I also generate the data in this form, the solution I've adopted is to fill two tables in FileMaker. One provides the summary view, the other the detailed view.
I think that your problem is down to dupliate records and an inadequate key.
Create a text field called "App_Prog". In the options box set it to an auto-enter calc, unchecking the 'Do not replace...' option, and use the following calc:
Application & "_" & Program
Now create a self join to the table using App_Prog as the field on both sides, and call this 'MatchingApps'.
Now, create (if you don't alread have one) a unique serial number field, 'Counter' say, and make sure that you enter a value in each record. (Find all, click in the field, and use serial number option in'Replace Field Contents...')
Now add a new calc field - Is_Duplicate with the following calc...
If (Counter = MatchingApps::Counter; "Master Record" ; "Duplicate")
Finally, find all, click in the 'Application field, and use 'Replace Field Contents...' with a calculation to force the auto-enter calc for 'App_Prog' to come up with a value.
Where does this get you? You should now have a set of records that are marker either "Master Record" or "Duplicate". Do a find on "Master Record", and then you can perform your summary (by Application) to do a count of distinct application-program pairs.
If you have access to custom functions (you need FileMaker Pro Advanced), I'd do it like this:
Add the RemoveDuplicates function as found here (this is a recursive function that takes a list of strings and returns a list of unique values).
In the relationships graph, add another occurrence of your table and add an Application = Application relationship.
Create a calculated field in the table with the calculation looking something like this:
ValueCount(RemoveDuplicates(List(TABLE2::Program)))
You'll find that each record will contain the number of distinct programs for the given application. Showing a summary for each application should be relatively trivial from here.
I think the best way to do this is to create a separate applications table. So as you've given the data, it would have two records, one for A and one for B.
So, with the addition of an Applications table and your existing table, which I'll call Objects, create a relationship from Applications to Objects (with a table occurrence called ObjectsParent) based on the ApplicationName as the match field. Create a self join relationship between Objects and itself with both Application and Program as the match fields. I'll call one of the "table occurrences" ObjectsParent and the other ObjectsChildren. Make sure that there's a primary key field in Objects that is set to auto-enter a serial number or some other method to ensure uniqueness. I'll call this ID.
So your relationship graph has three table occurrences:
Applications::Applicaiton = ObjectsParent::Application
ObjectsParent::Application = ObjectsChildren::Application, ObjectsParent::Program = ObjectsChildren::Program
Now create a calculation field in Objects, and calculating from the context of ObjectsParent, give it the following formula:
AppCount = Count( ObjectsChildren::ID )
Create a calculation field in Applications and calculating from the context of the table occurrence you used to relate it to ObjectsParent with the following formula:
AppCount = ObjectsParent::AppCount
The count field in Objects will have the same value for every object with the same application, so it doesn't matter which one you get this data from.
If you now view the data in Applications in list view, you can place the Applications::Application and Applications::AppCount fields on the layout and you should get what you've requested.