Scenario: requesting the addition of a “Copy Previous” button in the Deposit record, which would allow for duplicating lines and simplifying the process of replicating previous entries without the need to manually re-enter the information.

basic script logic in pageInit:
- Wait for UI load: The script waits a short time after the page opens so the sublist buttons (Add, Cancel, etc.) are fully rendered.
- Find the right spot: It locates the HTML element for the “Remove” button and finds the row (
<tr>) that holds all line-level buttons. - Create the new button: It builds a new button (
Copy Previous) using the same structure and style NetSuite uses for its buttons. - Insert the button inline: The new button is inserted right after “Remove”, keeping it on the same line as Add/Cancel/Insert/Remove.
- Add click functionality: When clicked, the script reads data from the previous line, copies those values, and adds them to a new line.
- Show confirmation: A message pops up confirming that the line was copied successfully.
Script:
/**
* @NApiVersion 2.1
* @NScriptType ClientScript
*/
define([‘N/currentRecord’, ‘N/ui/dialog’], (currentRecord, dialog) => {
const sublistId = ‘other’;
const pageInit = () => {
try {
// Wait for NetSuite to render toolbar fully
setTimeout(() => injectCopyButton(), 1200);
} catch (err) {
console.error(‘Error injecting Copy Previous button:’, err);
}
};
const injectCopyButton = () => {
const removeTable = document.getElementById(`tbl_${sublistId}_remove`);
if (!removeTable) {
console.warn(‘Remove button table not found for sublist:’, sublistId);
return;
}
// Avoid duplicate injection
if (document.getElementById(`tbl_${sublistId}_copy`)) return;
// Go one level up — to the <td> containing “Remove” and then its parent <tr>
const removeTd = removeTable.closest(‘td’);
const buttonsRow = removeTd?.parentNode; // <tr> element that holds all <td> buttons
if (!buttonsRow) {
console.warn(‘Could not locate button row container.’);
return;
}
// Create a new <td> with full NetSuite button structure
const td = document.createElement(‘td’);
td.innerHTML = `
<table class=”machBnt” id=”tbl_${sublistId}_copy” cellpadding=”0? cellspacing=”0? border=”0? role=”presentation”>
<tbody>
<tr><td class=”bntTop”><img src=”/images/nav/ns_x.gif” width=”1? height=”3? alt=””></td></tr>
<tr>
<td class=”uir-copy bntBg” valign=”top”>
<input type=”button”
class=”nlinlineeditbutton bntBgT”
id=”custpage_copy_prev_linebtn”
value=”Copy Previous”
style=”font-weight: 500;”>
</td>
</tr>
<tr><td class=”bntBot”><img src=”/images/nav/ns_x.gif” width=”1? height=”3? alt=””></td></tr>
</tbody>
</table>
`;
// Insert our new button <td> right after the <td> that holds Remove
buttonsRow.insertBefore(td, removeTd.nextSibling);
// Attach click logic
const copyBtn = td.querySelector(‘#custpage_copy_prev_linebtn’);
copyBtn.onclick = () => copyPreviousLine();
console.log(‘Copy Previous button injected after Remove’);
};
const copyPreviousLine = () => {
const rec = currentRecord.get();
const lineCount = rec.getLineCount({ sublistId });
if (lineCount < 1) {
dialog.alert({ title: ‘Notice’, message: ‘No previous line found to copy.’ });
return;
}
const lastLine = lineCount – 1;
const fieldsToCopy = [
‘entity’, ‘account’, ‘paymentmethod’, ‘amount’,
‘department’, ‘class’, ‘location’, ‘memo’
];
rec.selectNewLine({ sublistId });
fieldsToCopy.forEach((fieldId) => {
try {
const value = rec.getSublistValue({ sublistId, fieldId, line: lastLine });
if (value !== null && value !== undefined && value !== ”) {
rec.setCurrentSublistValue({ sublistId, fieldId, value });
}
} catch (e) {
console.warn(`Skipping field ${fieldId}: ${e.message}`);
}
});
rec.commitLine({ sublistId });
dialog.alert({
title: ‘Success’,
message: ‘Previous line copied successfully.’
});
};
return { pageInit };
});