Hi @R.J
Your first question I am not sure I have an answer you want
however: I would probably create a different app (which you said you didnât want to do) or pass the data to an external DB but two other possibilities could be:
1. Create 12 hidden (this I think will easier with the new record) number fields on the records then at the end of each month write the value into the relevant months field then you can âdashboardâ on the fields.
-
Create a hidden text field then at the end of the month add the months value in this way:
[
["Month", "Value"],
["Jan", 2345],
["Feb", 2340]
]
You could then use a little script that pushed the current months value into the main array. From here you add a calculation field to the record and build a table from the JSON in the Text field.
let raw = ï»ż@dataï»ż;
// Try to parse, fallback to default if it fails - You probably don't need the first try block but when I was building it was messing me about
let data;
try {
data = JSON.parse(raw);
} catch (e) {
data = [["Month", "Value"]];
}
// main table build
let table = "<table border='1' style='border-collapse: collapse;'>";
for (let i = 0; i < data.length; i++) {
table += "<tr>";
for (let j = 0; j < data[i].length; j++) {
let cellTag = i === 0 ? "th" : "td";
table += `<${cellTag} style='padding: 4px 8px;'>${data[i][j]}</${cellTag}>`;
}
table += "</tr>";
}
table += "</table>";
//Display the table
table;
When I was building the table it was messing me around a little so I added the try at the top if you donât want it and you are sure you have suitable data in your text field you could remove it and replace the first line with:
let data = JSON.parse(@data)
NOTE: I have used a single line text field in my demo as it will leave your JSON intact however this has a length of 500 characters so you need to be carefull how much you put in.
Part Two
Not easily is as far as I am aware I think i would do it in one of two ways:
1. track changes by pushing changes to an external DB then doing the queries there
- It is technically possible to do this in Tape but it might depend on how many records you are trying to do this for, the theoretical process would be:
1. Search your records for those changed since your cut of date
2. Loop through those changed getting the revision history
tape.setApiKey(var_api);
const { data: rev } = await tape.RecordRevision.getMany(current_record_id);
console.info(JSON.stringify(rev,null,2));
When you get the revision history you get a response like:
{
"revisions": [
{
"created_by": {
"id": 67022,
"mail": [
"jason@jmc.tools"
],
"user_id": 67022,
"name": "Jason",
"org_id": 1703,
"type": "user"
},
"created_on": "2025-05-09 07:44:52",
"record_id": 153768387,
"revision": 0,
"type": "creation"
},
{
"created_by": null,
"created_on": "2025-05-09 07:44:56",
"record_id": 153768387,
"revision": 1,
"type": "update"
},
{
"created_by": {
"id": 67022,
"mail": [
"jason@jmc.tools"
],
"user_id": 67022,
"name": "Jason",
"org_id": 1703,
"type": "user"
},
"created_on": "2025-05-09 07:57:52",
"record_id": 153768387,
"revision": 2,
"type": "update"
}
],
"total": 3
}
From this you would need to:
- extract the dates
- find the date closest to your cut off date but more recent
- get the revision number
- subtract 1 from that number
This if my brain is working correctly will give you the record revision for the state at your cut off date, so armed with that number you can now get the record at that revision
const { data: oldRecord } = await tape.RecordRevision.getRevision({recordId: current_record_id,revisionId: 1});
console.info(JSON.stringify(oldRecord,null,2));
which will give you the record details for that revision:
{
"record_id": 153768387,
"app_record_id": 1,
"app_id": 60518,
"created_on": "2025-05-09 08:44:52",
"created_on_utc": "2025-05-09 07:44:52",
"last_modified_on": "2025-05-09 08:57:52",
"last_modified_on_utc": "2025-05-09 07:57:52",
"deleted_on": null,
"deleted_on_utc": null,
"fields": [
{
"field_id": 610930,
"external_id": "name",
"label": "Name",
"type": "text",
"field_type": "single_text",
"config": {
"label": "Name",
"slug": "name",
"external_id": "name",
"show_description": false,
"required": false,
"always_hidden": false,
"hidden_if_empty": false,
"settings": {
"formatted": false
}
},
"values": [
{
"value": "t1"
}
]
},
{
"field_id": 610932,
"external_id": "data",
"label": "data",
"type": "text",
"field_type": "single_text",
"config": {
"label": "data",
"slug": "data",
"external_id": "data",
"show_description": false,
"required": false,
"always_hidden": false,
"hidden_if_empty": false,
"settings": {
"formatted": false
}
},
"values": [
{
"value": "[[\"Month\", \"Value\"], [\"Jan\", 2345], [\"Feb\", 2340]]"
}
]
},
{
"field_id": 610933,
"external_id": "calculation",
"label": "Calculation",
"type": "calculation",
"field_type": "calculation",
"config": {
"label": "Calculation",
"slug": "calculation",
"external_id": "calculation",
"show_description": false,
"required": false,
"always_hidden": false,
"hidden_if_empty": false,
"settings": {
"decimals": 0,
"return_type": "text",
"script": "let raw = @[data](field_610932);\n\n// Try to parse, fallback to default if it fails\nlet data;\ntry {\n data = JSON.parse(raw);\n} catch (e) {\n data = [[\"Month\", \"Value\"]];\n}\n\nlet table = \"<table border='1' style='border-collapse: collapse;'>\";\n\nfor (let i = 0; i < data.length; i++) {\n table += \"<tr>\";\n for (let j = 0; j < data[i].length; j++) {\n let cellTag = i === 0 ? \"th\" : \"td\";\n table += `<${cellTag} style='padding: 4px 8px;'>${data[i][j]}</${cellTag}>`;\n }\n table += \"</tr>\";\n}\n\ntable += \"</table>\";\n\ntable;",
"calendar": false,
"unit": null
}
},
"values": [
{
"value": "<table border='1' style='border-collapse: collapse;'><tr><th style='padding: 4px 8px;'>Month</th><th style='padding: 4px 8px;'>Value</th></tr><tr><td style='padding: 4px 8px;'>Jan</td><td style='padding: 4px 8px;'>2345</td></tr><tr><td style='padding: 4px 8px;'>Feb</td><td style='padding: 4px 8px;'>2340</td></tr></table>",
"value_string": "<table border='1' style='border-collapse: collapse;'><tr><th style='padding: 4px 8px;'>Month</th><th style='padding: 4px 8px;'>Value</th></tr><tr><td style='padding: 4px 8px;'>Jan</td><td style='padding: 4px 8px;'>2345</td></tr><tr><td style='padding: 4px 8px;'>Feb</td><td style='padding: 4px 8px;'>2340</td></tr></table>",
"decimal": null,
"start": null,
"start_date": null,
"start_date_utc": null,
"start_time": null,
"start_time_utc": null,
"start_utc": null
}
]
}
],
"created_by": {
"mail": [
"jason@jmc.tools"
],
"id": 67022,
"user_id": 67022,
"org_id": 1703,
"name": "Jason",
"type": "user",
"email": "jason@jmc.tools"
},
"last_modified_by": {
"mail": [
"jason@jmc.tools"
],
"id": 67022,
"user_id": 67022,
"org_id": 1703,
"name": "Jason",
"type": "user",
"email": "jason@jmc.tools"
}
}
Now you will need to check the record to see if it would have fallen into your view and if it would save the record_id and the revision id for doing whatever you want with later.
I donât think any of that actually gives you what you were after but hopefully it gives you some ideas. However bottom line is if you want âpoint in timeâ data I would pass it to something else: a different app, external SQL or even the JSON service that @Luis talked about in the April 2025 Official Tape Partner Roundtable Webinar.