Your will need to learn how to create scripts as that is what you need if you want this to happen automatically on a schedule. I suggest looking for a tutorial on the subject that can supplement anything posted here in the forum.
The first part of your task is to come up with a script that finds all records meeting the following criteria:
Today's date is 30 days or later than the date stored in the person's record
The form letter has not yet been printed.
The second option can be handled by putting a value in a status field to show that this task has been done. Your find can then find all records meeting the date requirement that also have this field empty.
You might try setting up a manual find to find such records as a first step in getting this to work. Putting a lone = in a field while in browse mode specifies that you want all records where the field is blank. You can subtract 30 days from today's date and put that date into the date field with the < operator to find all records that have a date older than that date.
Then you can try your hand at scripting it. The script would look like similar to this:
#Script must be performed on a layout based on your personnel table.
Go to layout ["Personnel" (Personnel) ]
Enter Find Mode  ---> clear the pause check box.
Set Field [Personnel::Date30 ; "<" & Get ( CurrentDate ) - 30 ]
Set Field [Personnel::FormLetterStatus ; "=" ]
Set Error Capture [on]
Perform Find 
This script is patterned after the scripted find examples found here: Scripted Find Examples
Note: When Setting up Set Field, there are two Specify buttons that must be clicked. To get Set Field [Table::Field ; Expression], add set field to your script and click the first button (specify target field). Select Table::Field from the list of fields. Do not click the specify button next to the repetition box. Click OK to close this dialog box. Now click the lower specify button (calculated result) and create the expression to the right of the semicolon (;). Do not try to type in the semicolon.