Bingo script is filling in repeat numbers

I have made a script that fills in an InDesign file bingo card to generate as many as requested.
It works almost flawlessly. However, there is one part that perplexes me. The problem is obviously in the core of the script, where the numbers get chosen and then supposedly culled from the list of available choices. However, I get repeats of numbers, usually the final item in each list can get two or sometimes three repeats.

The code is below. If I have missed something or if there is just some weird memory issue happening, I would love to know what it is, and how to correct it. Thanks so much!

set textItems to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75"}

set BItems to items 1 thru 15 of textItems
set IItems to items 16 thru 30 of textItems
set NItems to items 31 thru 45 of textItems
set GItems to items 46 thru 60 of textItems
set OItems to items 61 thru 75 of textItems


set ThisPlace to (choose folder with prompt "Where do you want to save your bingo cards?")
--return ThisPlace


set BatchNumber to (display dialog "How many bingo cards do you want?" default answer "1")
set BatchRound to text returned of the result --to get the number of bingo cards being generated
--return BatchRound

tell application "Adobe InDesign 2025"
	set user interaction level of script preferences to never interact --This allows the document to revert without requiring a dialog to OK
end tell

repeat with u from 1 to BatchRound
	set ThisRun to u as string
	--return ThisRun
	
	tell application "Adobe InDesign 2025"
		
		set TheName to the name of document 1
		--return TheName
		my CullName(TheName, ThisRun, ThisPlace) --this gets rid of the " Template.indd" part of the file name and builds the full path for each file
		set ThisDoc to result
		--return ThisDoc
		
		
		tell document 1
			set theTextLabels to the count of text frames
			set TextFrameNames to the id of text frames
			--return TextFrameNames
			--return theTextLabels
			set textFrames to the label of text frames
			--return textFrames
			set BankOne to (the text frames whose label contains "B")
			--return BankOne
			set BankTwo to (the text frames whose label contains "I")
			--return BankTwo
			set BankThree to (the text frames whose label contains "N")
			--return BankThree
			set BankFour to (the text frames whose label contains "G")
			set BankFive to (the text frames whose label contains "O")
			--return BankFive
			
			
			--Let's do each bank of text frames with numbers 
			
			set theBankz to {BankOne, BankTwo, BankThree, BankFour, BankFive}
			set ItemSetz to {BItems, IItems, NItems, GItems, OItems}
			
			repeat with b from 1 to 5
				
				set thisBank to item b of theBankz --this resets the sets of numbers before going through another card run
				--return thisBank
				set theseItemz to item b of ItemSetz
				--return theseItemz
				
				
				--below is the core of the script, but we need to go though each bank of text frames before moving on to the others
				repeat with i from 1 to (count of items of thisBank)
					
					set randNumb to random number from 1 to count of items of theseItemz --sets random number from bank for specified column
					--return randNumb
					set thePull to item randNumb of theseItemz -- we  need the specific item not it's count number
					
					set randFrame to item i of thisBank
					--return randFrame
					set (contents of randFrame) to thePull as string
					-- this works! Now we need to pull the used items out of the sets
					--return
					if randNumb is less than or equal to ((count of items of theseItemz) - i) then
						if randNumb is greater than 1 then
							set textItemsStart to items 1 thru (randNumb - 1) of theseItemz
							--return textBItemsStart
							--pull out the item we used
							set textItemsNext to items (randNumb + 1) thru end of theseItemz
							--return textBItemsNext
							set theseItemz to textItemsStart & textItemsNext
							--return BItems
						else if randNumb is 1 then
							set theseItemz to items 2 thru end of theseItemz
						end if
					end if
					--return BItems
					
					--return BankOne
				end repeat
				
			end repeat
			
			--return
		end tell
		save a copy document 1 to alias ThisDoc
		revert document 1
		
	end tell
end repeat

tell application "Adobe InDesign 2025"
	set user interaction level of script preferences to interact with all
end tell




on CullName(TheName, ThisRun, ThisPlace)
	set thisName to (characters 1 through ((offset of " Template.indd" in TheName) - 1) of TheName) as string
	set thePath to ThisPlace & thisName & "_" & ThisRun & ".indd" as string
	return thePath
end CullName

Also attached is my InDesign file to use for testing. Thanks!

Bingo Card Template.indd.zip (455.9 KB)

T_Rex. I don’t have inDesign and can’t test your script. It looks like a fun project, and I’m sure another forum member will provide a solution.

FWIW, ASObjC does a great job of shuffling a series of numbers, and I’ve included an example below. The first time you run the script, it takes about a third of a second to load the required frameworks into memory. Once the frameworks are in memory, the script takes 4 milliseconds to run on my computer.

use framework "Foundation"
use framework "GameplayKit"
use scripting additions

--a list of shuffled numbers for each bingo card column
set B to items 1 thru 5 of getShuffledNumbers(1, 15)
set I to items 1 thru 5 of getShuffledNumbers(16, 30)
set N to items 1 thru 5 of getShuffledNumbers(31, 45)
set G to items 1 thru 5 of getShuffledNumbers(46, 60)
set O to items 1 thru 5 of getShuffledNumbers(61, 75)

--this section creates a bingo card and is for testing only
set bingoCard to "B  I  N  G  O" & linefeed --bingo card header
set item 3 of N to "**" --free square
repeat with j from 1 to 5
	set aRow to ""
	repeat with aColumn in {B, I, N, G, O}
		set aNumber to text -2 thru -1 of ("0" & (item j of aColumn))
		set aRow to aRow & aNumber & space
	end repeat
	set bingoCard to bingoCard & aRow & linefeed
end repeat

on getShuffledNumbers(startNumber, endNumber)
	set numberArray to current application's NSMutableArray's new()
	repeat with k from startNumber to endNumber --create an array from startNumber to endNumber
		(numberArray's addObject:k)
	end repeat
	set randomSource to current application's GKMersenneTwisterRandomSource's new()
	set shuffledArray to randomSource's arrayByShufflingObjectsInArray:numberArray
	return shuffledArray as list
end getShuffledNumbers