How do I get Data from a each key in the datastore

Admin Panel

  • So I created a admin panel with in-game logs and discord logs.
    Here is how I save the data in a table:
local saveSuccess, saveError = pcall(function()
		BanDataStore:SetAsync(tostring(userId), {
			Banned = true,
			ExpirationTime = expirationTime,
			AdminName = admin.Name or "Unknown Admin",
			TargetPlayer = targetPlayer.Name,
			Reason = reason,
			TargetID = targetPlayer.UserId,
		})
	end)

I’m using this to get the data

local function getBanData(player)
	local success, pages = pcall(BanDataStore.ListKeysAsync, BanDataStore)

	if success then
		local banData = {}
		while true do
			local items = pages:GetCurrentPage()

			for _, dataStoreKey in ipairs(items) do
				local success, value = pcall(BanDataStore.GetAsync, BanDataStore, dataStoreKey)

				if success and type(value) == "table" and value.TargetPlayer and value.AdminName and value.Reason and value.ExpirationTime then
					table.insert(banData, {
						TargetPlayer = value.TargetPlayer,
						AdminName = value.AdminName,
						Reason = value.Reason,
						ExpirationTime = value.ExpirationTime
					})
				else
					warn("Invalid or incomplete data in DataStore for key:", dataStoreKey)
					warn("Value:", value)
				end
			end

			if pages.IsFinished then break end
			pages:AdvanceToNextPageAsync()
		end

		RefreshEvent:FireClient(player, "RefreshBanData", banData)
	else
		warn("Error listing keys:", pages)
	end
end

So I pass the bandata through this

RefreshEvent:FireClient(player, "RefreshBanData", banData)

Local script:

local function updateBanLogs(banData)
	
	for _, banInfo in ipairs(banData) do
		local newLog = Template:Clone()
		newLog.Parent = BanLogsScrollingFrame
		newLog.Name = banInfo.TargetPlayer
		newLog.TargetUsername.Text = "Target: " .. banInfo.TargetPlayer
		newLog.AdminUsername.Text = "Admin: " .. banInfo.AdminName
		newLog.BanReason.Text = "Reason: " .. banInfo.Reason

		newLog.Select.MouseButton1Click:Connect(function()
			targetPlayer = banInfo.TargetPlayer
			UnBanFrame.Visible = true
			UnBanFrame.Reason.Text = "Unban reason for " .. targetPlayer
		end)
	end
end```
local Refreshbutton = script.Parent.RefreshButton

Refreshbutton.MouseButton1Click:Connect(function()
	RefreshEvent:FireServer("RefreshBanData")
end)

RefreshEvent.OnClientEvent:Connect(function(eventType, data)
	if eventType == "RefreshBanData" then
		for _, logFrame in ipairs(BanLogsScrollingFrame:GetChildren()) do
			if logFrame:IsA("Frame") then
				logFrame:Destroy()
			end
		end

		for _, banInfo in ipairs(data) do
			updateBanLogs(banInfo.targetPlayer, banInfo.adminUsername, banInfo.banReason, banInfo.banLength)
		end
	
	elseif eventType == "LogBan" then
		local targetPlayer = data.targetPlayer
		local adminUsername = data.adminUsername
		local banReason = data.banReason
		local banLength = data.banLength
		updateBanLogs(targetPlayer, adminUsername, banReason, banLength)
		print("Logged.")
	end
end)

So it creates a template with the information from each key in the datastore but it just doesn’t work.

3 Likes

You need to use the KeyName property of the DataStoreKey returned by the items table like in this example:

local DataStoreService = game:GetService("DataStoreService")

local ExampleStore = DataStoreService:GetDataStore("ExampleStore")

local success, pages = pcall(ExampleStore.ListKeysAsync, ExampleStore)

if success then
	while true do
		local items = pages:GetCurrentPage()

		for index, dataStoreKey in items do
			local success, value = pcall(ExampleStore.GetAsync, ExampleStore, dataStoreKey.KeyName)

			if success then print(value) end
		end

		if pages.IsFinished then break end
		pages:AdvanceToNextPageAsync()
	end
end
3 Likes

Thank you the error is not showing anymore, but It’s just not creating the template based off the data

local function updateBanLogs(banData)
	for _, banInfo in ipairs(banData) do
		print("banInfo:", banInfo)
		print("banInfo.TargetPlayer:", banInfo.TargetPlayer)

		local newLog = Template:Clone()
		newLog.Parent = BanLogsScrollingFrame
		newLog.Name = banInfo.TargetPlayer
		newLog.TargetUsername.Text = "Target: " .. banInfo.TargetPlayer
		newLog.AdminUsername.Text = "Admin: " .. banInfo.AdminName
		newLog.BanReason.Text = "Reason: " .. banInfo.Reason

		newLog.Select.MouseButton1Click:Connect(function()
			targetPlayer = banInfo.TargetPlayer
			UnBanFrame.Visible = true
			UnBanFrame.Reason.Text = "Unban reason for " .. targetPlayer
		end)
	end
end
local Refreshbutton = script.Parent.RefreshButton

Refreshbutton.MouseButton1Click:Connect(function()
	RefreshEvent:FireServer("RefreshBanData")
end)

RefreshEvent.OnClientEvent:Connect(function(eventType, data)
	if eventType == "RefreshBanData" then
		
		for _, banInfo in ipairs(data) do
			updateBanLogs(banInfo)
		end

		print("Logged.")
	end
end)
1 Like

Add a print statement inside of this loop to see if the updateBanLogs function is running

1 Like

I did that and this is what it printed:
image
But I noticed it printed 10 times so that means 10 keys
image

2 Likes

Is banInfo: (the ban info) being printed in the output? If not then that means the banData is an empty table so there might be an issue with how you’re saving it to your DataStore

I also recommend adding a print statement before the banData loop starts to print the banData value to confirm this

1 Like

It’s not empty I checked all of them
image

This is how its stored.

2 Likes

Still I recommend you check your output to see if it’s being printed, and also add that print statement to make sure

1 Like

Can you add me on discord if you’re willing to help me more, I would really appreciate that.
Discord: vvshenok

1 Like

Unfortunately I don’t have a Discord account

There’s also the possibility that you might be accidentally parenting the newLog to the BanLogsScrollingFrame that’s still inside of StarterGui instead of the one inside of PlayerGui

2 Likes

That might be a solution but also I am getting the same error for some reason even tho it was working fine.


image

The data is also still there.

2 Likes

That error explains what’s happening quite well: banInfo is nil

The fact that the for loop is running but banInfo is nil means the banData table isn’t being saved correctly, so I don’t know what method are you using to be able to correctly read the data saved inside of it

2 Likes

Here is the Timeban function

local function TimeBanPlayer(targetPlayer, lengthInDays, reason, admin)
	local userId = targetPlayer.UserId
	local currentTime = os.time()

	if type(lengthInDays) ~= "number" or lengthInDays <= 0 then
		warn("Invalid lengthInDays value. Aborting ban.")
		return
	end

	if IsPlayerBanned(userId) then
		local existingBan = BanDataStore:GetAsync(tostring(userId))
		KickBannedPlayer(targetPlayer, existingBan.Reason)
		return
	end

	targetPlayer:Kick(reason, "Rejoin to see what you were banned for.")

	local durationInSeconds = lengthInDays * 24 * 60 * 60
	local expirationTime = currentTime + durationInSeconds

	local saveSuccess, saveError = pcall(function()
		BanDataStore:SetAsync(tostring(userId), {
			Banned = true,
			ExpirationTime = expirationTime,
			AdminName = admin.Name or "Unknown Admin",
			TargetPlayer = targetPlayer.Name,
			Reason = reason,
			TargetID = targetPlayer.UserId,
		})
	end)

	if saveSuccess then
		print("Saved ban entry for player:", targetPlayer.Name)
	else
		warn("Error saving ban info to DataStore:", saveError)
	end

	local existingBan = BanDataStore:GetAsync(tostring(userId))
	remoteEvent:FireClient(targetPlayer, targetPlayer, admin.Name, reason, lengthInDays)
	module.SendBanWebhook(BanDataStore:GetAsync(tostring(targetPlayer.UserId)), targetPlayer, admin)
end
1 Like

This might be activating incorrectly, which will exit out of the function before SetAsync is used to save the banData table, otherwise unfortunately I don’t see anything else that might be causing the issue to happen

Edit to add: @Vvshenok Just in case do remember that you need to add:

if game:GetService("RunService"):IsStudio() then
	game:BindToClose(function()
		task.wait(1)
	end)
end

when testing DataStores in Studio otherwise the server closes too quickly for the data to successfully finish saving, which might also be causing you problems

2 Likes

These are bans from like a day ago so it’s already in the datastore.

I tried doing this but still the same error:

RefreshEvent.OnClientEvent:Connect(function(eventType, data)
	if eventType == "RefreshBanData" then

		local logs = {}
		for _, banInfo in ipairs(data) do
			table.insert(logs, {
				TargetID = banInfo.TargetID,
				TargetPlayer = banInfo.TargetPlayer,
				AdminName = banInfo.AdminName,
				Reason = banInfo.Reason
			})
		end
		updateBanLogs(logs)
	end
end)

At this point it might not be looking inside the key.

1 Like

See if adding a guard clause to the for loop inside of the updateBanLogs function works like so:

local function updateBanLogs(banData)
	for _, banInfo in ipairs(banData) do
		if not banInfo then continue end

		print("banInfo:", banInfo)
		print("banInfo.TargetPlayer:", banInfo.TargetPlayer)

		local newLog = Template:Clone()
		newLog.Parent = BanLogsScrollingFrame
		newLog.Name = banInfo.TargetPlayer
		newLog.TargetUsername.Text = "Target: " .. banInfo.TargetPlayer
		newLog.AdminUsername.Text = "Admin: " .. banInfo.AdminName
		newLog.BanReason.Text = "Reason: " .. banInfo.Reason

		newLog.Select.MouseButton1Click:Connect(function()
			targetPlayer = banInfo.TargetPlayer
			UnBanFrame.Visible = true
			UnBanFrame.Reason.Text = "Unban reason for " .. targetPlayer
		end)
	end
end
1 Like

I found out why I was getting the error again, it’s because I deleted a Data using the DataStore Editor
image

1 Like

That would explain why banInfo was nil :sweat_smile:

Hopefully the templates are being created as you’d wish now :slight_smile::+1:

1 Like

Well the problem is I’m probably gonna have to use new data because not that I deleted the table inside the key but the key is not deleted.

Actually I found a way, I can import a luau file.

1 Like

Okay so it worked but one more error which idk why its doing that.


image
image