Events

In Spread, when a Threaded Comment is changed, an event is triggered to notify about the data change. You can handle these changes by binding to the event and responding accordingly.

The ThreadedCommentChanging event occurs before the threaded comment changes (such as before replies are added/edited/removed, or before solved status changes). You can set args.cancel = true to prevent the change: The ThreadedCommentChanged event occurs when the threaded comment has changed (such as replies added/edited/removed, or solved status changed). The CellChanged event can also be used to detect when a threaded comment is added or removed from a cell: The UserMentioned event occurs when a reply containing one or more mentions is added to a threaded comment:
window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); initSpread(spread); }; // User IDs in GUID format var USER_IDS = { ALICE: "{715CFD19-2BB9-4B94-DE0C-08D0F9A019DB}", BOB: "{8A3E2F47-5C1D-4E8B-A9F2-3B7C6D8E9F01}", CAROL: "{C4D5E6F7-8A9B-0C1D-2E3F-4A5B6C7D8E9F}", DAVID: "{D1E2F3A4-B5C6-7D8E-9F0A-1B2C3D4E5F67}" }; function initSpread(spread) { // Configure UserManager first configureUserManager(); spread.suspendPaint(); var spreadNS = GC.Spread.Sheets; var sheet = spread.getActiveSheet(); sheet.options.allowCellOverflow = true; // Create a sample data table createSampleTable(sheet); // Add threaded comments to demonstrate various APIs addThreadedComments(sheet); // Add event listeners var threadedCommentEvent = document.getElementById("threadedCommentEvent"); // Listen for CellChanged event to detect threaded comment add/remove sheet.bind(spreadNS.Events.CellChanged, function(e, args) { if (args.propertyName === "threadedComment") { var text = threadedCommentEvent.value; if (text !== "") { text += '\n'; } var eventType; var hasOldValue = args.oldValue !== null && args.oldValue !== undefined; var hasNewValue = args.newValue !== null && args.newValue !== undefined; if (!hasOldValue && hasNewValue) { eventType = "Add threaded comment"; } else if (hasOldValue && !hasNewValue) { eventType = "Remove threaded comment"; } else if (hasOldValue && hasNewValue) { eventType = "Set threaded comment"; } else { eventType = "Threaded comment changed"; } threadedCommentEvent.value = text + "CellChanged: " + eventType + " at (" + args.row + ", " + args.col + ")"; } }); // Listen for ThreadedCommentChanged event with enhanced output sheet.bind(spreadNS.Events.ThreadedCommentChanged, function(e, args) { var text = threadedCommentEvent.value; if (text !== "") { text += '\n'; } var propertyName = args.propertyName; var eventDetail = "ThreadedCommentChanged at (" + args.threadedComment.row() + ", " + args.threadedComment.col() + "): " + propertyName; // Enhance output based on property name and value if (propertyName === "resolved") { eventDetail += " = " + (args.newValue ? "true" : "false"); } else if (propertyName === "reply") { var hasOldValue = args.oldValue !== null && args.oldValue !== undefined; var hasNewValue = args.newValue !== null && args.newValue !== undefined; // Get reply index information var replyIndex = args.replyIndex; if (!hasOldValue && hasNewValue) { eventDetail += " (Add reply at index " + replyIndex + ")"; } else if (hasOldValue && !hasNewValue) { eventDetail += " (Remove reply at index " + replyIndex + ")"; } else if (hasOldValue && hasNewValue) { eventDetail += " (Edit reply at index " + replyIndex + ")"; } } threadedCommentEvent.value = text + eventDetail; }); // Listen for UserMentioned event with enhanced output sheet.bind(spreadNS.Events.UserMentioned, function(e, args) { var text = threadedCommentEvent.value; if (text !== "") { text += '\n'; } var context = args.context; var userIds = args.userIds; // Create an array of promises to get all user information var userPromises = []; for (var i = 0; i < userIds.length; i++) { userPromises.push(GC.Spread.Common.UserManager.get(userIds[i])); } // Wait for all promises to resolve Promise.all(userPromises).then(function(users) { var userNames = []; for (var j = 0; j < users.length; j++) { var user = users[j]; userNames.push((user && user.name) || "Can't find the user who's id is " + userIds[j]); } var pluralText = userNames.length > 1 ? "are" : "is"; var eventDetail = userNames.join(", ") + " " + pluralText + " mentioned at (" + context.threadedComment.row() + ", " + context.threadedComment.col() + ")"; threadedCommentEvent.value = text + eventDetail; }); }); spread.resumePaint(); } function configureUserManager() { // Mock user database with GUID-style IDs and avatars var users = [ { id: USER_IDS.ALICE, name: "Alice Johnson", email: "alice.johnson@company.com", avatar: { kind: "data", dataUrl: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAJ/0lEQVR42u2beVBURx7HN8Yym9JU7W7VJtbW5o+NuhqT0ogYEW88cDAcCnIoEg4VDwSFgQFEjnhxK+fIpSiHAg7XcA6nMAOogNyXQBBBREEEYe6Z33Y/9aGORXQph0nCH996r997PdOf9zv61z3wFwD4U2kaeBp4GngaeBp4GhhpZHjoH51tzUvLi/N0UuMvH2fERNgzYiKxqMW5TKPm+rsqTweezJVKpZ/8boH5PO7susqKjeF+py/Y7NWpMtry44D2qm9FGsrzQUN5HuAjlqbKIsmujcuGDxtqNJz3oF1mF2TrDQ89/efvBlgsFs2srmBv9bC1TN+1YdkIZfk8AnD7igXw04//fafwPQxPWf4N6KguFtia6lWw0pPMeVzubIUGHno68GXkhXO++mpKQwiUhPxQaaC+2gjcy9nmeldH2/cKCdzV3va9i5UpC0FKSdBJaQHgl2a5S735VmmhpkIBYyvYmulV4AFOHlTW2ns1VveW38zXVgjggf6+fzsc2F1Cwn4E4RxgprWhC2fzKQUWCgWfhXq5h6CEI/0IoDKWdthvxH468HjulAFXlBRo6a5f+pyM2Y8s9D2S2LAADzRfz5A7MHdsbI6rtUU26cryAEZTlzly7QddHQvlDlxzu2yT7rqlo+SA5ActTYwOc5IrMC4BLwV6e+NkIm9gHMtOh4yLeNyxOXID5o6NzrHfZ8SWjzvLVmV71FUe46lQbsC93b/O/3n72h6UneUOjIVrck5h7k65Abc11Snrb1Qa/pjZWUf1W/C0MQRDtR9kSlTczmLEH/zDAFOQ55yw0IQnVQkQ7m75hwLGg8fWJNs4TA7qrIVm1kUQd2RDT1kMHNFdj64vmDrgey0NSgZqy4cmA6yB+mqpLIJz1vpw6rAuBiJgrfQ2QG1GEIjaM0HQloGOWcAMc8HPvt5fmpOSsF9uwI8fPfzaQketc+KkNfHa13y7CiQHOcDTmhsI2gBfJ8A7iy+RsFjCe5kwUJ0IVGN1ePV9O1Z/J6gsK9kmz2npC3sLQ84HTEukBfdsVoIgZzNoL4wkwEbqk8GPagxJAfbwrPYGCfu6xB1ZkBJMI18Y3j3pbGtZItfCI8TTjY52KCayJGlN7VWL4ID2GghzOwBNuXTgtTBJMG5zGjyuvA4CZEnhuGSAM8NcXlZa8+CQAaVpaHDgK7mWlnlMhpnmyoXiN1wVQxIutxiMNi2DvRRVOH3UAAqvnoLe8lgyJkkY0m1fwafDwzuJMFDDIK7xWtLJ+6EuFkBZPh8oSt8A2glJkIjFM+UKfL+j7TvjbaqPMOgO1cXEgFJDHCHW5zi4WxlCoOsh8HKngb8HFR4gWDEJ+m5hi7NiPCHQyw0CTjtAQZwXZESdIrxhCMW57e4thLdsR0qJu2Qr98WDUCic5elknfgqjtPpzgBdufDoznVwPGQIlA0rQVV5KTqqQH1uGIgmBiZeSKSnLdFntfIS2Km+DqK87Qjr1jADQX/9EgJ299aVT9pbGpWmZD1cmp+1C2+2YVejmWqgpMMg3LIu+yIkBJ0AH6cDkHzRDUYbU8fhWpnARYmK25Ai49bdZbEQ8stRCPKwgqzoM6gdg++h2N9PJD2cMzyRO+ONhykBfj4y/HcXKzMWHgiO28KYMzjBYGviI4aQybp8FJe8xhTgIqHzt6HJPrg/VntRFJhprCSqLwM15SG8LJ3SPS08AMPNKwYpSvPAbs9W6L9zjUxCk9UYyuAXaCYYFhcewvjIYFcxSlZTCiyRiD9NvHzRGbk2H8cY/eQ+GGtKezc0usZvZZLnglZ8lAElrZ0ZfpIoO9Fn86ICvXzQGni2QmzTCgT8v+LfjPaor+rTWrkQYj2PIujUV9Ak4LPSK9CCYrQLxfX9cHdoO2MDwzhOx58j+xRfPQ3Gm5Uklnrqjay0JHMBn/+5Qm3E42KktaF2hY8HLU6foioMQdPUQwQjwhBYKK570VTD0VKDMp3NUKa9Ccp3boH+1EB8j3hGhKz9rI4BKWGuYGG6QxwQ7BPb19s9T2F/aunncb+Nqq/KOsaIFR3wPwUeoWeghI0KiRZsNVRIoNKx/dxxqDTWhCpTHbgf6gKCxlQCdhg9U1eHCozsOLCJiwDb3FTpmTvsblZ3xy98sXiOQgIX9fzqeLwkF+w5+UArKwBqaR7QSnPBp5wFSZU5wKnLgYa7TGgqioGW0nhoqc+E23XZkFadA0G3WHCCkwdUdj44oL4O6DPsSlngWl70rG90ZIlCAj/mji1M6WgO9q0ua6Sx88UO7DzAskeivjx35uQhiHxwQ8KANOIeeZ+Uc1kBL7j2Nqekt8tWoKgWxnrwfFg5oOZWJRq0ZBxAVvb4OIGcOPn8pHuNkVyR6G8KG8Mo1r4Ib6jKo5ayyIFPUhIUJjRFBp4T2VCdQy2dLCjpBVKFBsZ6ODqy9Dw7r9HhZjZKXgVIKAlhsSfSOCTt5dGuNFd6rbU++rlQ8KVCAwt53NnX/R1KfM8egbNXL4BbWgy45DDAqSAdnAqZL1TABOf88bZjYQbY3swB6+JsOFiQASa5KWCUlSS+1dezS+H/xqP//r0f6DaaA+GHt8Ilm58g0m4nhDkaoZLTBOiuPyOZQpCzMQQ57cFtQiHu5nAwLgT0s2/AbiTzvFSwKsoCRnsTXQrSGQoNXFucZulvsV4abkUhgAlZbyd1GbX9TNdhEefEtaMU8Ak8Aa+SHY2IXxZ4VrI7Bvnc/ygssFQi+TQn6my0n9laiDhKAMvo8jFN8DVdj0WcE9cQdKjHPnAqypTJ0sU9XVSFBR4dHpwb7WLS5G++DgFrTAxsRgITVg5zMoITuQwiwZFZGlnct6qsaZCHrKyIwD1ttWuDDqs/P79vA0RODIz0JnC4gz64ZCWQwK9DowIkSiiRfK5wwHdyrtn7ma+VXti/ESKt3xsY6U1g2aqrgJ/f3ekikkg+I0IHYAYucsRSyawpAxaLRbNSA53SfE3XAAn8AS4dQTOAk9mJ7wS2f1Fbc1Pam0Nwvf5MwP/Xpca7mUjptx/17EO19my5A48M9n8d5WjUgSxMAEchiPe1MFaEgx6czLwmA/yWe+PM3XmlqSYeTVsjtmhl5sjJF6AXEYoXGHIF7mq4vTXg4BYempL+P2B7XTiZET8hMBaeruwQ6N6cZDj8IqtjaGFFX48lAHwiN+BKFL94OnpvYLO3gKm64MqM+y1gcp4+UpSFKrJk3Cbmb2T1VIlUOlMewHgjb2ZGqGuSt8kqwDFMTEtHtkGkFUVGUSh7e+9dA94mq/E5eT3imBa4MqLB7gXAbwq7M67KbHDNjtrMzlZ/nMzkAywSzqrMuU7Nu+JLz4/xoxfE+tM5CcH0ssSQdyiUnnfFDwufk9c5SXR6RjWHzuhooSe3N7+XkFXpiW0NoZyH3VZokfHV9L8ATAP/yYD/BxmCzyIgvhWGAAAAAElFTkSuQmCC" } }, { id: USER_IDS.BOB, name: "Bob Smith", email: "bob.smith@company.com", avatar: { kind: "data", dataUrl: "data:image/png;base64,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" } }, { id: USER_IDS.CAROL, name: "Carol Manager", email: "carol.manager@company.com", avatar: { kind: "data", dataUrl: "data:image/png;base64,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" } }, { id: USER_IDS.DAVID, name: "David Accountant", email: "david.accountant@company.com", avatar: { kind: "data", dataUrl: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAMCElEQVR42u2bCVRU5xXHm6XN0iRNT096kvY0pzltmtOTtmmJiKhsUkXBhWOiJjHRqCyy7wPDMjNsApEl2kSFGPZFUPadiGAFCZuobAMMi4JEFlkGmH3m9n6f4wuWhuNBYGiL5/zPvHnvzffu79773W95+CMA+L/SKvAq8CJJIpE8NTMz8xzqxX/T8yKR6GmVSvXfC0yMHx4e/kVVdbV+XHy8fWBQ0Al7R8cLFlZW5ZZWVjWoWrW+xXMVNra2WVwe74sz0dGOF8vLjQYGBn6pVCpXPDAFbWtrezMiMpLz4f799YabNgl1N2yAdevXP7L0DAymd7///vVjISGh9fX17ygUiidWJLBYLP5JXELCoe07d/KJ4QR0g57egvTASVu2bu2PiIryHRoa+vmKAp6YmHgOIxKA0ZlZv3EjMXpRhG0ReKWtvX1Gb2/vbzQMzBSjp0+cPMleo6Mj0WVgF1frMOJHbWyyBwcHX9E4cFZOzu6N+vrjWtraj5bGC09zFYfHi5qenn5GY8D9/f2vvbdnT+M7WlrwF5T2unVLBowiBW0qOydnl8aA09PTD+ro6iownWGtri6sWbt2qaMMltbWeUKh8NllB5bJZE96stnxBJSk8yIXqx88j5X7TktLy1vLDjw+Pv7S/k8++ZZ4/V2MLNH6RYI1MzMBQyND+E9FEOuFtLSszHTZgXGYeN1sx44eOnSg/rpmDfxNWxsNokbTyoqfjwh5vxLrGxgAy/EwNJedheyvj8FuczNM44faoONzUnLykWUHFggEf9xmZjZEoaghG8DY2BDOneZBXJQPOFh9DOY7TcFokxG9joaTex6Wur+bmPwd7Cz3Q25sCIzdyASFoAjkgkJoKDwDH+41pw6dDZyYlOS27MC1tbVaRsbG4w8MMTA0gJQveSDvKqTGCluyoacqCa7mfEGj9VUEGyL8nSHQyxb8PW0gAD9PBLnBhZgguF4SA+M3s+jvZF0FIO2kIuD099vNtqqzhQFmLzvw5cuXtfUNDSceRI/lcBgmmrPR4EJqrByNVfUUUym6i8h35pqkgwJR59BoohAURSFRzL30MxYzZiM+R6PANTU1Wrg4GCee37zFmEZCoTZczM8HfkUcVGWdhO4riSChEZtfCEbTub7gNNTmnYKRpvPkHNVg3Tk48NF7xLGaA+7q6np7q6npiA4a4GJzAFM4hxo3iVE+FcoC021baBHatcMUUjHVRfy8eWE7KxPAyfoT0udphbY+9AFNdZm6i8R97otpzQC7Lztwd3f377Fo9ROvp3zBZQoNMdLN/lOICnTFPs2FM2GeEM5zgqHGDGL8DwIXJX0GoX4OkHiSA19HeoOPiyV1HDqKtt38zVnYhk7UuQ9ss+zAA/39r+40N28nEakvPE2MosZPt+XCJBase9czob/2HI28pCOfaL6UpmA0mrQf33fMxM0s/B3t2zTdLQ7uw+mrrjLtXPre5QNWKZ5WTvSZi2/VpMZE+E4c+ngP3K5J/b7IoPpqM0HQdg3yc7PA29UKBr5NY67/gCjUcFMmtFbnQUlGNFwrip5dsanDgrzt4MM95oqb1YVRKtG9P4FK9cSSAyunBrdIu4ruSTvyQNSeS/veVGsuY9hkcxYUZyUBv6MTcNuGjrVJ/+CQSjwfMI3mjZoyEAqn4LPwCNizezt0Xk4A+SxH8Svi4VZNCh7nq2SCUoFy6jv9JQdWDDcHS/m5ILmZgToP8k4mVUl06fjr7nAETLaZ0mFEBycYMcfZ8wFTqN7qZAgJ9oeAoCDYbGJCf1ucdJwOabPvk7Vlg6QlE4gN8sHGMyTKSwzcGiDGB07WJoGwLhlEzZlzClB+fCit0noG+nAQh5O28lhS0OZLZ9rnj2JlfnetDujorqe/xwL4kKMk7TkgakyFmYYUELdcAPmduhQEfnJpU3qy31TcnisaqkqEO5diYeRq8pyChOMwrarl5yKh72oK0xcZ8fNQuXMcdaP0K/BzswIX24NQmBiG7Tzc7nj9ObhbGQd3L8fDDDpaMdLGXvqipZD+VD5QGy9qzVZNXsuAqevnHwbuKgapoJRGFNORgMyBlbRi9W3LIZqT2qRaz2CllwlKsK1Z3QCfMdGYDqPYhyebMkDaXdauEo+/tSzDkko28wp6lyXvry6T3b5Siw8XMIb1VoC0vwaPZ4My00ZqOPZ16hCEp5+oOdGmbfT9kzmH8CLUGDp0SHbryjdK4R1DANUy72kp5c+hXsKHG0sFxSOzjZ5pZ2ZWFGgcx9GS5OMQxnGEmHA2FCSEwTEfezrJ4F+Ko5AoZkwWdxBIxhEy4mDlzIgWDkdvY5a9qNl9aZXyKcVwiy8xjBqMsGWp4TB2nRY02jc9HA6RFRWt2npkSbjJiB7jTI2ue9NO8UjhollQk/slDnfxNMVpRvTXZKgUkpdW1psHhexF+d0bnyOgnBSbILYdsJ0t6OeO7dvur3/VS7zDODZz1+vCFj2yeUAX/7Si21p8BBE8ZzhyYC80kQpNVlB9lRdVkok3Vua7JaXsBYy0n6KndKSpOBqscJjZvNmYLAjots2BXabA0d8AKTracEFnDZzU1QFbE2N4z9yMuW8Xbhqc+cwTC1eeWDFYm4qwv13RL9MG7wz8Kik6oryxKIYuGHAMJjsXdJZ0FycXt1OPQ1skG1qOs6DrNBe+K4mG21dT6Jh7DZ10C4+7ryRBVnxke08X/88r+mVaR0fHG0FBwfnOzi4KG2tc7YRzoflSMty7kUWrtpws7nuKZ4sZuqax33dXp0HZ+RhgeziDo6Oj0o/DqeDz+W+vSGB8xflrHo9X7OvrC0E4PTxy5Ai4uLjicSAE83wg7esTcDHzK6grToCGYox6SSzUl8TDlbxYyEs9DSePBwKP4wuBgUHg4OgIpB0ul0tU3dnZ+eaKAp6amno+KirqrLe3NwQHB4O/vz9YWFiAn58f/e7p6QkODo4QEBAAbDYb3N3d8ZovuLq6gj+e8/Jig729Pb2O99Pr+Bt67OPjA8eOHcscGxt7WdPAzDvh3NzcA2i8iEQWRUGPHj2K0QoE9TkKZG1tDba2toCZQGE8PDzIfdQ56syg59FxBJoeqx0gT0lJcV6Md8WLkcqvYjQaEYIxmETRycmJHDPAHA6HgmHEmPPEIXZ2duDs7DznXnQg851E3s3NrRP//U7jwDk5OYdJBNQGM5FDMRCzDJ/9nYFGMdFUdwns/y7kPNMmi8VSJSYmemJGaQ4YX10+i0blYWFhANA4Gh1MSwZ4PuE9tAtgRjBCONIGA4yiTsDnVOHL959pDBh3Lv/g4OAwoDaMERpNIfD4kYT9lwxDjBCYpDCFxOuz68BYU1OTtsaAKysrd+7bt0/h7uGBxgVAAIKTqotOAHWffmTNTmn8TosWh8tl2vT09IK9e/dCdnb2IY0BFxQUfHDUyrLTxc5C5styggBfD+Cw3aT2drYSpr8uTAjsJvdhuUhJm36ezuBqb6m0trLoyczMtNEYsEgken70jkBvuD59dLghHUZwQ4BfHtfh48XqYdJ8geJyOSM3SuM6R7FN0jY+QzQ60LkT68YLmh2HRaPrZIIioYy+JyrELZ2MJm+2163HgFVPOLxHm4rPNii7yTqZSqoS9ptqfFhSTt42wyWhFEWXc+0VqVVsttfdhQMzhWysoTihctY2rUo50XtQ48BoxKfEGBQoELiuKP6ihwfrnrr4LFgcDld47WJ6DjpR+WBPSzHS7qFxYLL1QoxRAyvry9KyWZ5ewscG5vJmGi5lJSOwjAEeag7XPPDQzQgGGPvZxczYVDd3D9GCgZn5tI+4+EL8l4quoik1MNmHTgCV8gnNAePD0YgkBlhQLMxOjj7l5OQseVxgLzZblp+REI5tjjDA/VeLQKX4ieaAlfJn5LerS78HLhnOSYuNtLGxlT8usAeLpcjPTOUoer7pocCd+SDrrahTyaWam1qq5JKXcZOtCrdTxbhnLFb0XWrLz0xjW1paTYeEhIhDQ0MXpLCwMDFOL2cKci54KPoq60jbRLLeS824J/6aJlP6x7j7v1YpGjUiIscjw0Ovt7a2GuKfNRn19fUtWLgUNBwZGX4dN/G0aPtU93Qxq55d/T8Pq8CrwKvAq8D/q/oX/qMBfgXyOKsAAAAASUVORK5CYII=" } } ]; // Configure UserManager with mock implementation GC.Spread.Common.UserManager.configure({ get: async function(userId) { if (userId === undefined) { return; } return new Promise(function(resolve) { var user = users.find(function(u) { return u.id === userId; }); resolve(user); }); }, search: async function(query) { return new Promise(function(resolve) { resolve(users.filter(u => u.name.toLowerCase().includes(query.toLowerCase()) || u.email.toLowerCase().includes(query.toLowerCase()) )); }); } }); // Set current user GC.Spread.Common.UserManager.current(USER_IDS.ALICE); } function addThreadedComments(sheet) { var threadedCommentManager = sheet.threadedComments; // Example 1: Simple threaded comment with one reply on Reserve var tc1 = threadedCommentManager.add(9, 2); tc1.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "Please verify if 10% reserve is sufficient for this quarter." } ], authorId: USER_IDS.ALICE, createdAt: new Date() }); // Example 2: Threaded comment with multiple replies on Total Budget var tc2 = threadedCommentManager.add(10, 2); tc2.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "The total budget looks reasonable." } ], authorId: USER_IDS.ALICE, createdAt: new Date(Date.now() - 86400000) // 1 day ago }); tc2.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "Confirmed. Ready for approval." } ], authorId: USER_IDS.BOB, createdAt: new Date(Date.now() - 43200000) // 12 hours ago }); tc2.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "Approved!" } ], authorId: USER_IDS.CAROL, createdAt: new Date() }); // Example 3: Resolved threaded comment on Operations var tc3 = threadedCommentManager.add(4, 2); tc3.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "Should we increase the operations budget?" } ], authorId: USER_IDS.BOB, createdAt: new Date(Date.now() - 172800000) // 2 days ago }); tc3.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "No, this amount aligns with our Q3 plans." } ], authorId: USER_IDS.ALICE, createdAt: new Date(Date.now() - 86400000) // 1 day ago }); // Mark this thread as resolved tc3.resolved(true); // Example 4: Comment with mention and link on Development variance var tc4 = threadedCommentManager.add(3, 4); tc4.add({ message: [ { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: "Hey " }, { type: GC.Spread.Sheets.ThreadedComments.ContentType.mention, userId: USER_IDS.DAVID }, { type: GC.Spread.Sheets.ThreadedComments.ContentType.text, value: ", please review the budget variance in Development department: " }, { type: GC.Spread.Sheets.ThreadedComments.ContentType.link, href: "https://example.com/budget-policy", text: "Budget Policy" } ], authorId: USER_IDS.ALICE, createdAt: new Date() }); } function createSampleTable(sheet) { // Set column widths sheet.setColumnWidth(1, 150); sheet.setColumnWidth(2, 120); sheet.setColumnWidth(3, 100); sheet.setColumnWidth(4, 120); // Display current user in B1 sheet.setValue(0, 1, "Current User: Alice Johnson"); sheet.getCell(0, 1).font("bold 11pt Arial").foreColor("#4A90D9"); // Headers sheet.setValue(1, 1, "Department"); sheet.setValue(1, 2, "Q3 Budget"); sheet.setValue(1, 3, "Q3 Actual"); sheet.setValue(1, 4, "Variance"); sheet.getRange(1, 1, 1, 4).font("bold 12pt Arial"); // Department budget data sheet.setValue(2, 1, "Marketing"); sheet.setValue(2, 2, 15000); sheet.setValue(2, 3, 14200); sheet.getCell(2, 4).formula("=C3-D3"); sheet.setValue(3, 1, "Development"); sheet.setValue(3, 2, 25000); sheet.setValue(3, 3, 26800); sheet.getCell(3, 4).formula("=C4-D4"); sheet.setValue(4, 1, "Operations"); sheet.setValue(4, 2, 10000); sheet.setValue(4, 3, 9850); sheet.getCell(4, 4).formula("=C5-D5"); sheet.setValue(5, 1, "Sales"); sheet.setValue(5, 2, 18000); sheet.setValue(5, 3, 17500); sheet.getCell(5, 4).formula("=C6-D6"); sheet.setValue(6, 1, "HR"); sheet.setValue(6, 2, 8000); sheet.setValue(6, 3, 8200); sheet.getCell(6, 4).formula("=C7-D7"); sheet.setValue(7, 1, "IT Support"); sheet.setValue(7, 2, 12000); sheet.setValue(7, 3, 11600); sheet.getCell(7, 4).formula("=C8-D8"); // Subtotal row sheet.setValue(8, 1, "Subtotal"); sheet.getCell(8, 2).formula("=SUM(C3:C8)"); sheet.getCell(8, 3).formula("=SUM(D3:D8)"); sheet.getCell(8, 4).formula("=SUM(E3:E8)"); sheet.getRange(8, 1, 1, 4).font("bold 11pt Arial"); // Reserve calculation sheet.setValue(9, 1, "Reserve (10%)"); sheet.getCell(9, 2).formula("=C8*0.1"); sheet.setValue(9, 3, ""); sheet.setValue(9, 4, ""); sheet.getCell(9, 1).font("bold 11pt Arial"); sheet.getCell(9, 2).font("bold 11pt Arial"); sheet.getCell(9, 2).backColor("#FFEB9C"); sheet.setValue(10, 1, "Total Budget"); sheet.getCell(10, 2).formula("=C8+C9"); sheet.getCell(10, 3).formula("=D8"); sheet.getCell(10, 4).formula("=C11-D11"); sheet.getRange(10, 1, 1, 4).font("bold 12pt Arial"); sheet.getRange(10, 2, 1, 3).backColor("#C6EFCE"); sheet.getRange(2, 2, 9, 3).formatter("$#,##0.00;[Red]-$#,##0.00"); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> <div class="options-container"> <textarea id="threadedCommentEvent" style="width: 100%; height: 100%" readOnly placeholder="Event log: Threaded Comment events will be displayed here..."></textarea> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; overflow: auto; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; } textarea { width: 100%; height: 80px; padding: 6px 12px; box-sizing: border-box; } .sample-options { z-index: 1000; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }