Creating "complex forms" in FileMaker - is it even possible? - database

I have been asked to look into FileMaker for creating a pretty simple database app. The application will handle contact information, some information about events hosted by the organization and - and this is where I'm currently struggling - RSVP information that link the contacts and events, as well as stores some data about payment.
What I would like to use is some kind of form where the user gets to search for a contact (any combo of first/last name) and an event (any combo of name/date), select each from two respective lists (where all other information is displayed as well, to distinguish the results), add some extra information and hit submit.
The closest I've gotten so far is a form where the user can enter a ContactId and EventId manually, which means that he/she first has to go to another view, search for the records, and copy/paste the id numbers.
Is there really no way to get closer to my vision using FileMaker?
Would a better option be to build a new, custom app using for example C# and MsSQL?
If so, how do I sell this to my contractor? As this would in that case be my first commercial application, there is obviously a "safety factor" that speaks in favor of an established product. And then we haven't even mentioned that the cost would probably increase, as developing a new app from scratch would take much longer time.
Note: I have no previous experience with FileMaker. I've tried to read the documentation, but I haven't been able to find any tutorials that take me closer to my specific needs. I'm fairly experienced in MsSQL, so I do know this and that about database management in general - just not in FileMaker.

There are loads of ways to do it. This is a quick way to get it to work.
Let's say you have two tables like this:
Contacts Events
-------- --------
ContactID EventID
FirstName EventDate
LastName EventDetails
Create a new link table between them that also stores the extra RSVP information you want.
RSVP
--------
fk_ContactID
fk_EventID
PaymentInfo
Create a FORM table
FORM
--------
ContactSearch
cContactMatch = Calculation, If(isEmpty(ContactSearch) ; "ALL" ; ContactSearch)
EventSearch
cEventMatch = Calculation, If(isEmpty(EventSearch) ; "ALL" ; EventSearch)
Add the following fields to the Contacts and Events tables:
Contacts
--------
cMatchField = Calculation, Stored, (FirstName + NEWLINE + LastName + NEWLINE + ALL + NEWLINE + Firstname LastName)
Events
--------
cMatchField = Calculation, Stored, (EventDate + NEWLINE + EventDetails + NEWLINE + ALL)
This means that the cMatchField for Contacts will look something like this:
John
Smith
John Smith
ALL
In the relationship diagram, connect the tables like this:
FORM
--------
cContactMatch = CONTACTS/cMatchText
cEventMatch = EVENTS/cMatchText
Create a layout called FORM based on the FORM table.
Add the fields ContactSearch and EventSearch to the layout. Add the PaymentInfo field.
Add two PORTALS to the layout, one for the Contacts table, one for the Events.
By default you should see all the records in each of these portals.
Write a script, or use a script trigger, that refreshes the layout whenever one of those search fields is Exited/Modified. This should refresh the portals and show you the related records you're interested in.
Add a button to each row in the portals and call a script that sets a global variable to that portal rows ID.
For example:
Script: Set Selected Contact ID
Set Variable ($$ContactID ; Contacts::ContactID)
Script Set Selected Event ID
Set Variable ($$EventID ; Events::EventID)
Add another button to the layout and a new script.
Script: Create RSVP
# Check that a contact and event have been selected
If(isEmpty($$ContactID) or isEmpty($$EventID)
Exit Script
End If
# Get the payment info that has been entered
Set Variable ($PaymentInfo ; FORM::PaymentInfo)
# Create the RSVP Link record
Go To Layout(RSVP)
Create New Record
Set Field(fk_ContactID ; $$ContactID)
Set Field(fk_EventID ; $$EventID)
Set Field(PaymentInfo ; $PaymentInfo)
Commit Records
Go to Layout (Original Layout)
# Clear the search fields
Set Field(PaymentInfo; "")
Set Field(ContactSearch; "")
Set Field(EventSearch; "")
Set Variable($$ContactID; "")
Set Variable($$EventID; "")
Commit Records
Refresh Screen
Phew.
And you should be back, ready to search for Contacts, Events, and "Submit" the form to create more RSVPs.
FileMaker is fun, eh?

Related

Oracle APEX looping through CheckBox Group elements

I need to make the function of inserting data into several tables at once in the ORACLE APEX App Builder. Interactive report displays information from the View collected from the tables "Book", "Autors_list", "Autor", where "Autors_list" is needed to reveal the many-to-many relationship between the author and the book.
So, on an automatically created form, when I click on the CREATE button, using a dynamic event, I try to add data to the "Book" and "Autors_list" tables.
The data I'm trying to add:
P15_ID_BOOK - book id - add to "Book" and to "Autors_list"
P15_BOOK_NAME - book name - add to "Book"
P15_AUTORS - authors - are represented using the Checkbox Group - I need to go through each of its elements and for each element add an entry to the "Autors_list" in the form (P15_BOOK_NAME, author id from P15_AUTORS)
P15_PUBLICATION_DATE - publication date - add to "Book"
P15_PRICE - book's price - add to "Book"
The CheckBox Group is set using the following List of Values
`
select "id_autor", (CONCAT(CONCAT(autor."Name", ' '),autor."Surname")) as "Autors" from "Autor" autor;
`
I wrote the following PL/SQL code to add the above values to the tables:
begin
insert into "Book"
("Name", "Publication_date", "Price")
values
(:P15_BOOK_NAME, :P15_PUBLICATION_DATE, :P15_PRICE);
FOR i IN (select * from table(apex_string.split(:P15_AUTORS, ',')))
LOOP
insert into "Autors_list"
values (:P15_ID_BOOK, i);
END LOOP;
end ;
However, it gives me an error
ORA-01008: not all variables bound
Please tell me how to cycle through the elements of the Checkbox Group correctly and get the values from there
Typically this is not how you would do this in apex. You say So, on an automatically created form, when I click on the CREATE button, using a dynamic event, I try to add data to the "Book" and "Autors_list" tables.
If the form is automatically created, then a page process will be created to handle the insert into "book" for you. There is no need to create a dynamic action (not "dynamic event") to do this. Everything will be done when the page is submitted. That is the "normal" flow in apex: a page is rendered, the user enters data, and then the page is submitted (and all processing is done). Dynamic actions are used to manupilate the dom, perform ajax callbacks, etc - all the things that do not require a page submit.
The only think that is left to be done is to create an additional page process to insert the child records in the "Authors_list" table. That page process needs to happen after the form process since the value for :P15_ID_BOOK will be generated on insert of the record in to books.
The code of your page process will be something like what you already have
FOR i IN (select * from table(apex_string.split(:P15_AUTORS, ',')))
LOOP
insert into "Autors_list"
values (:P15_ID_BOOK, i);
END LOOP;

Filling form automatically

I do not know way which I can fill my form automatically. I mean that I made easy database which has just table. I made form too. User can write some information about herself/himself, for example name. If he/she end filling places to fill he/she should click send button and all information (expect ID - it gives admin) are on database. User can edit his/her information by clicking button - when he/she click it, it is possibility to write ID - when ID is ready, user can click button load data which fill all places by information connected with this ID.
I tried make some SQL query but it does not work. I past part of my code in window below, but I tried many combination of vba and sql - it always look very easy.
Private Sub button_wczytaj_Click()
OK_imie_wpr.Text = Select OK_imie from Karta_projektu where
Numer_projekt_wpr = Numer_projekt
Form.Refresh
End Sub
button_wczytaj - button which load my data.
OK_imie_wpr - it is place where user can write his name - for example: Tom
OK_imie - it is place where i hold name on my table.
Numer_projekt_wpr - it is blocked place, user get his/her project ID from admin.
Numer_projekt - it is place where I hold ID on my table.
Karta_projektu - it is name of table.
I expect that when I fill place for ID and click load button I get all data connected with my ID. Something like:
SELECT OK_imie from Karta_projektu where ID = [And here i need id which user just write].
select load Button Goto- Property- goto Event Propert- onlick Event-
'Assume your Textbox where you write your ID is Name as 'TxtID'
Dim Query1 as string
Query1 = "SELECT OK_imie from Karta_projektu where ID = " & Me.TxtID & " "
Me.Form.Recordsource = Query1
Me.Form.Requery
I hope you have created a Bound Form.

How to set value in a field by UI?

I use three fields in Sqlserver Datavbase tables, for prevent delete records permanently by user:
IsDelete (bit)
DeletedDate (DateTime)
DeletedUserID (bigint)
I wish to set third field (DeletedUserID) by UI by some thing like this:
this.ExamdbDataSet.AcceptChanges();
DataRowView row = (DataRowView)this.BindingSource.Current;
row.BeginEdit();
row["DeletedUserID"] = User.User.Current.ID;
row.EndEdit();
this.ExamdbDataSet.AcceptChanges();
row.Delete();
and other two fields ,'IsDeleted' field and 'DeletedDate' are set automatically in table's 'After Delete Trigger'.
then commit changes to database with desire command successfuly with this code:
this.TableAdapterManager.UpdateAll(this.ExamdbDataSet);
but problem is , the 'DeletedUserID' is null in database.
and Question is : How to set 'DeletedUserID' field value by true way in UI?
I don't think it is a good way to do that. You have sliced a simple logic to separate parts, each being done in a different part of the application (UI, Trigger, ...). You set value of some field, and then DELETE the whole record! Don't expect anything else that the current situation.
You would better set all fields in UI (i.e. no trigger in this case), and change the query that loads data. For example,
Select * from table1 where IsDeleted=0
You didn't tell us anything about whether your use ASP.Net or WinForms. Give us more info.

Salesforce Junction Objects

To all salesforce experts i need some assistance. I have my contacts and a custom object named programs. I created a junction object using to master detail relationships with contacts and programs. I want to avoid relating the same contact to the same program. I tried triggers but I couldn't create the testing part to use it outside sandbox.
I went back to the basics and created a Unique text field. I tried to use default value but EVERYTHING i write in that crap is wrong -_-. I tried Contact__r.Email & "-" & Program__r.Name but to no avail.
I tried workflow rules with a field update but my field update NEVER runs.(Yes I did activate the workflow rule) and I didn't know what to write in my rule's code.
The workflow firing condition could be simply a formula that says true. Alternatively use "every time record is inserted". It also depends whether your master-details are set once and that's it or they will be "reparentable" (option introduced in Summer '12 I think). Maybe post a screenshot / text description of your firing condition? Also - is your unique field set to "case sensitive"?
As for the formula to populate the unique field - something like Contact__c + ' ' + Program__c (or whatever the API names of your fields are) should be OK. Don't use Contact__r.Email etc as these don't have to be unique...
You'll have to somehow fill in the uniqueness criteria for all existing records (maybe that's why you claimed it doesn't work?). If you can use Apex for data fixes - something like this should get you started.
List<Junction__c> junctions = [SELECT Contact__c, Program__c
FROM Junction__c
WHERE Unique_Text_Field__c = null
LIMIT 10000];
for(Junction__c j : junctions){
String key = String.valueOf(j.Contact__c).left(15) + ' ' + String.valueOf(j.Program__c).left(15);
j.Unique_Text_Field__c = key;
}
update junctions;
Keep rerunning it until it starts to show 0 rows processed. The Ids are cut down to 15 chars because in Apex you'd usually see full 18-char Id but workflows use 15-char versions.

Trigger Duplicate CSV

am trying to upload a CSV file / insert a bulk of records using the import wizard. In short I would like to keep the latest record, in case if duplicates are found. Duplicates record are a combination of First name, Last name and title
For example if my CSV file looks like the following:
James,Wistler,34,New York,Married
James,Wistler,34,London,Married
....
....
James,Wistler,34,New York,Divorced
This should only keep in my org: James,Wistler,34,New York,Divorced
I have been trying to write a trigger before an update / insert but so far no success Here is my trigger code: (The code is not yet finished (only filering with Firstname), I am having a problem deleting found duplicate in my CSV ) Any hints. Thanks for reading!
trigger CheckDuplicateInsert on Customer__c(before insert,before update){
Map <String, Customer__c> customerFirstName = new Map<String,Customer__c>();
list <Customer__c> CustomerList = Trigger.new;
for (Customer__c newCustomer : CustomerList)
{
if ((newCustomer.First_Name__c != null) && System.Trigger.isInsert )
{
if (customerFirstName.containsKey(newCustomer.First_Name__c) )
//remove the duplicate from the map
customerFirstName.remove(newCustomer.First_Name__c);
//end of the if clause
// add this stage we dont have any duplicate, so lets add a new customer
customerFirstName.put(newCustomer.First_Name__c , newCustomer);
}
else if ((System.Trigger.oldMap.get(newCustomer.id)!= null)&&newCustomer.First_Name__c !=System.Trigger.oldMap.get(newCustomer.id).First_Name__c )
{//field is being updated, lets mark it with UPDATED for tracking
newCustomer.First_Name__c=newCustomer.First_Name__c+'UPDATED';
customerFirstName.put(newCustomer.First_Name__c , newCustomer);
}
}
for (Customer__c customer : [SELECT First_Name__c FROM Customer__c WHERE First_Name__c IN :customerFirstName.KeySet()])
{
if (customer.First_Name__c!=null)
{
Customer__c newCustomer=customerFirstName.get(customer.First_Name__c);
newCustomer.First_Name__c=Customer.First_Name__c+'EXIST_DB';
}
}
}
Purely non-SF solution would be to sort them & deduplicate in Excel for example ;)
Good news - you don't need a trigger. Bad news - you might have to ditch the import wizard and start using Data Loader. The solution is pretty long and looks scary but once you get the hang of it it should start to make more sense and be easier to maintain in future than writing code.
You can download the Data Loader in setup area of your Production org and here's some basic info about the tool.
Anyway.
I'd make a new text field on your Contact, call it "unique key" or something and mark it as External Id. If you have never used ext. ids - Jeff Douglas has a good post about them.
You might have to populate the field on your existing data before proceeding. Easiest would be to export all Contacts where it's blank (from a report for example), fill it in with some Excel formulas and import back.
If you want, you can even write a workflow rule to handle the generation of the unique key. This might help you when Mrs. Jane Doe gets married and becomes Jane Bloggs and also will make previous point easier (you'd just import Contacts without changes, just "touching" them and the workflow will fire). Something like
condition: ISBLANK(Unique_key__c) || ISCHANGED(FirstName) || ISCHANGED(LastName) || ISCHANGED(Title)
new value: Title + FirstName + ' ' + LastName
Almost there. Fire Data Loader and prepare an upsert job (because we want to insert some records and when duplicate is found - update them instead).
My only concern is what happens when what's effectively same row will appear more than once in 1 "batch" of records sent to SF like in your example. Upsert will not know which value is valid (it's like setting x = 7; and x = 5; in same save to DB) and will decide to fail these rows. So you might have to tweak the amount of records in a batch in Data Loader's settings.

Resources