Programmatic Cut/Copy/Paste

Posted by: menzel on 11 September 2020, 2:05 am EST

    • Post Options:
    • Link

    Posted 11 September 2020, 2:05 am EST

    I am trying to do programmatic cut, copy and paste operations. I need these two operations to be distinct, however, and function as a typical cut, copy and paste might in any application. In other words:

    • The user performs one actions to initiate the cut/copy, and a second to initiate the paste
    • The cut/copy needs to place the data from the selected range into the clipboard so it can be accessed outside of SpreadJS if needed.
    • The cut/copy triggers the dashed border around the selection.
    • I need to be able to trigger identical behavior using both a context menu option and a keyboard shortcut (I believe I know how to do this).

    Now, I have seen a number of similar questions on this forum, so before I get the same answer given here: https://www.grapecity.com/forums/spreadjs/copypaste-from-outside-spr (which is taken verbatim from documentation I have already read), let me be clear that this is NOT an answer to my question. I don’t know why that answer keeps getting recycled for posts about copy, but it very clearly mentions only the clipboardPaste command, and is doing single operation copy/pastes and cut/pastes. This does not meet my needs.

    That being said, the documentation here: https://www.grapecity.com/spreadjs/docs/v13/online/SpreadJS~GC.Spread.Sheets.Commands_namespace.html very clearly indicates the existence of a distinct copy command. It does not, however provide any examples of its use or explain in any useful what how to use it. Does this command actually work? If so, how?

    Furthermore, going back to the clipboardPastes mentioned above, EVERY example I have seen of that command’s use very clearly has a fromRanges and a pastedRanges parameter. This, implies then that there isn’t actually a “cliboardPaste” occurring, but rather some programmatic movement of data from one provided range to another. If it’s pasting from the clipboard, why do we need to provide a fromRange? If I omit the fromRange, does the command actually pull data from the clipboard? Is there some SpreadJS clipboard construct I need to provide to the command? Again, none of this is discussed in documentation.

    I have also tried the commands used in the default context menus (gc.spread.contextMenu.copy and gc.spread.contextMenu.pasteXXX), but not only do they not work for my specific use case (I have a locked header row and this seems to cause issues with the paste), but it doesn’t actually seem like the gc.spread.contextMenu.copy operation copies to the clipboard (as when I try to paste outside SpreadJS, the pasted value is whatever I copied prior to triggering the gc.spread.contextMenu.copy).

    I have also seen the copyTo() method, but again, I need distinct operations, not a single-click combined copy/paste.

    So, to summarize:

    1. Can I please get a concrete example of how the copy command (GC.Spread.Sheets.Commands.copy) works?
    2. Can I please get a concrete example of how to use clipboardPaste (GC.Spread.Sheets.Commands.clipboardPaste), or a similar command (I see there is a straight paste command) to paste from the actual clipboard?

    If the above commands are non-functional or for whatever reason cannot actually do clipboard operations, an acknowledgement of this would save me (and likely others) a lot of head banging.

    1. And if I can’t use your commands do do this, is there a way to programatically toggle the cutCopyIndicator so I can provide a visual cue that whatever manual implementation I come up with is actually doing something? (I see the docs here: https://www.grapecity.com/spreadjs/docs/v13/online/clipboard.html but they only discuss the boolean cutCopyIndicatorVisible, which seems like it determines if an indicator will be displayed when triggered, but does not do the actual triggering).

    Thank you.

  • Posted 15 September 2020, 1:27 am EST

    Hi Rick,

    Please refer to the following responses:

    1). Copy command does work, but please note that browsers provide limited access of the clipboard to webapps so SJS is unable can’t read/write from/to clipboard without user action such as pressing of ctrl+c key. Copy command would work correctly if used inside ctrl+c keydown handler. Here is a sample demonstrating the same: https://codesandbox.io/s/spread-js-starter-forked-oyts1?file=/src/index.js

    2). Similar to copy command, paste command i.e pasting from clipboard would only work if used inside handler for ctrl+v event.

    When using the clipboardPaste command you could perform paste operation whenever required but paste operation is limited to/from sheet of spreadjs workbook. You could set options like the source sheet, target sheet, source range, target range, whether you are performing cut/copy operation etc. Please refer to the example shown in the following document:

    https://www.grapecity.com/spreadjs/docs/v13/online/SpreadJS~GC.Spread.Sheets.Commands.clipboardPaste.html

    3). We are sorry but there is no public API exposed to trigger the cutCopyIndicator.

    Hope this helps!! Let us know, If there is still some confusion.

    Regards

    Sharad

  • Posted 15 September 2020, 7:30 am EST

    Because this seems to be a somewhat common issue here, let me summarize what I have learned over the last few days of digging and tinkering:

    The following command calls will do in-app cut/copy/paste (tested these all myself in SpreadJS 13 running in Angular 10):

    GC.Spread.Sheets.Commands.paste.execute(this.workbook, {sheetName: this.sheet.name()});
    GC.Spread.Sheets.Commands.cut.execute(this.workbook, {sheetName: this.sheet.name()});
    GC.Spread.Sheets.Commands.copy.execute(this.workbook, {sheetName: this.sheet.name()});
    

    The above commands use the current selection as the target area.

    None of the SpreadJS commands provided for this (including the misleadingly named clipboardPaste) actually use the clipboard due to browser security restrictions on clipboard access.

    If you REALLY need to use the clipboard, it is possible to access it using either Angular CDK (for copy only, apparently; don’t ask me why you only want to copy):

    const pending = this.clipboard.beginCopy(textToCopy);
    let remainingAttempts = 3;
    const attempt = () => {
    	const result = pending.copy();
    	if (!result && --remainingAttempts) {
    		setTimeout(attempt);
    	} else {
    		pending.destroy();
    	}
    };
    attempt();
    

    Or using the Clipboard API: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard.

    There are probably other methods for whatever flavor of Javascript you use, but I’m not an expert on them.

    You can intercept copy events by binding to the GC.Spread.Sheets.Events.ClipboardChanging event (this is where you could put the actual clipboard copy operation), or you can specify some custom function as the command in your Context Menu item definition which does the clipboard copy prior to or instead of the SpreadJS copy.

    In any case, you can still use keyboard shortcuts to do cut/copy/paste, provided that the target areas are not locked or otherwise edit-restricted (if they are, you will get a GC.Spread.Sheets.Events.InvalidOperation event, which you can also bind to for error messaging). Before you think about going down this road, no, you cannot just programatically generate a keydown event to fake the keyboard shortcut. Unfortunately browser devs anticipated this and Javascript generated events are not “trusted” and thus will not cause the same actions as actual Ctrl+x/Ctrl+c/Ctrl+v presses.

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels