You can set up a layout with global fields for DateStart, DateEnd and Description. Then a script can go to a layout for Staff and use a loop to create one such record in staff holidays for each staff member. The script can flip back and forth between layouts for Staff and Staff holidays. Staff has the found set of records that you are looping through and Staff Holidays is where the script changes to in order to create the new record. The script can include set field steps that copy the data out of the global fields and into the corresponding fields in Staff Holidays.
Ok, so I have a layout called Admin, with some settings, etc. on it.
This is where I put the new global fields and a button to start the following script.
Show Custom Dialog ["Are you sure? blah blah blah"] If[Get ( LastMessageChoice ) = 1] Set Variable [$Desc; Value:Admin::Description] Set Variable [$Start; Value:Admin::DateStart] Set Variable [$End; Value:Admin::DateEnd] Go to Layout ["Staff Details"] (Staff)] Show All Records #THIS FIND JUST LOOKS FOR ACTIVE EMPLOYEES Perform Find [Restore] Go to Record/Request/Page [First] Loop #IT'S IMPORTANT TO GO TO THE PORTAL OTHERWISE I'LL JUST BE CREATING NEW EMPLOYEES Go to Object [Object Name: "StaffHolidayPortal"] Go to Portal Row [Select; Last] Set Field [StaffHolidays::Description; $Desc] Set Field [StaffHolidays::DateStart; $Start] Set Field [StaffHolidays::DateEnd; $End] Commit Records/Requests  Go to Record/Request/Page [Next; Exit after last] End Loop End If
Not quite what I suggested. My outline would have the script using go to layout to go to a layout based on staff holiday to create the new record, then switches back to the Staff layout to go to the next record and continue the loop.
What you have works, but I prefer not to loop through portal rows if at all possible in a script. Later changes to the layout could result in such a script breaking. The method of switching back and forth between layouts, is a few percentage points less vulnerable to such issues.