Java – 从剪贴板中检索XML(Excel)电子表格

huangapple go评论69阅读模式
英文:

Java - Retrieve XML (Excel) Spreadsheet from clipboard

问题

我在想是否可以从Windows剪贴板获取原始的XML电子表格。因为当使用剪贴板查看器(https://www.freeclipboardviewer.com/windowsclipboard/)查看剪贴板时,XML Spreadsheet 是列出的一种格式之一。但是,当通过Java的Clipboard类查看可用的Dataflavors时,我只能找到text/plaintext/html,它们具有不同的编码和流/缓冲区/字符串/...

因此,使用自定义格式new DataFlavor("text/xml", "XML Spreadsheet"); 没有按照我的预期工作。虽然使用HTML也是一个选择,但我更希望获得电子表格,因为它包含一些额外的信息。

更新

我发现似乎可以通过Java FX Clipboard类实现这一点,但是自从Java 9以后,FX不再捆绑在一起了,这可能会很糟糕,而且初始化整个FX堆栈只是为了能够正确访问剪贴板也有点不太好。

英文:

I was wondering whether it's possible to get the raw XML spreadsheet from the windows clipboard. Since when looking into the clipboard with a clipboard viewer (https://www.freeclipboardviewer.com/windowsclipboard/), XML Spreadsheet is one of the listed flavors. However, when looking into the available Dataflavors via the Java Clipboard class, all I can find is text/plain and text/html with different encodings and streams/buffers/strings/...

Therefore using the custom flavor new DataFlavor("text/xml", "XML Spreadsheet"); didn't work as I expected. While using the HTML would be an option, I'd prefer having the spreadsheet, as it contains some additional information.

UPDATE

I've found out that this seems to be possible via the Java FX Clipboard class, however, since onward Java 9? FX isn't bundled anymore this would be quite bad and it would also kind of suck to have the whole FX stack inititalized just to be able to properly access the clipboard.

答案1

得分: 2

以下是翻译好的部分:

没有AWT或Swing的方法来获取Excel-XML(或二进制)数据。还可以查看2013年的JDK增强票据

您可以使用JavaFXSWT或“仅限Windows”的本机Win32 API通过JNA。来自Microsoft的Clipboard文档对我有很大帮助:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinDef.BOOL;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.UINT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.StdCallLibrary;

/**
 * 在Windows上显示Excel-XML剪贴板内容。请务必在Excel中选择一些单元格并使用“Ctrl+C”复制它们。
 * 
 * 作者:bobndrew
 */
public class WindowsSystemClipboardAccess {

    public interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
        int CountClipboardFormats();
        UINT RegisterClipboardFormatA(String lpszFormat);
        BOOL OpenClipboard(HWND hWndNewOwner);
        BOOL CloseClipboard();
        HANDLE GetClipboardData(UINT uFormat);
        DWORD GetLastError();
    }

    public static void main(String args[]) throws Exception {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        System.out.println("There are " + clipboard.getAvailableDataFlavors().length
                + " data flavors, but all are leading to a plainText- or htmlText-representation of the clipboard content:");
        for (DataFlavor flavor : clipboard.getAvailableDataFlavors()) {
            System.out.println(flavor.getHumanPresentableName() + "\t" + flavor);
        }

        System.out.println("\n\nSo we are using JNA to call the windows-API. The number of Windows-ClipboardFormats is "
                + User32.INSTANCE.CountClipboardFormats() + ".");

        UINT formatNumber = User32.INSTANCE.RegisterClipboardFormatA("XML Spreadsheet");
        System.out.println(formatNumber);
        System.out.println(User32.INSTANCE.OpenClipboard(null));
        HANDLE xmlData = User32.INSTANCE.GetClipboardData(formatNumber);
        System.out.println(xmlData);
        System.out.println(Kernel32.INSTANCE.GetLastError());
        System.out.println(Native.getLastError());
        System.out.println(User32.INSTANCE.CloseClipboard());

        System.out.println("\n" + xmlData.getPointer().getString(0));
    }
}

这个SSCCE示例的最后一行产生的xml如下:

<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 <Styles>
  <Style ss:ID="Default" ss:Name="Normal">
   <Alignment ss:Vertical="Bottom"/>
   <Borders/>
   <Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
   <Interior/>
   <NumberFormat/>
   <Protection/>
  </Style>
 </Styles>
 <Worksheet ss:Name="Tabelle1">
  <Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="4"
   ss:DefaultColumnWidth="62.400000000000006" ss:DefaultRowHeight="14.4">
   <Row>
    <Cell ss:Index="2"><Data ss:Type="Number">1.2</Data></Cell>
    <Cell><Data ss:Type="Number">123</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="String">A String with 1 Number</Data></Cell>
    <Cell ss:Formula="=R[-1]C+R[-1]C[-1]"><Data ss:Type="Number">124.2</Data></Cell>
   </Row>
  </Table>
 </Worksheet>
</Workbook>

如果您想要进行更多的探索,还可以在Windows的“剪贴板查看器链”中注册您的应用程序窗口进行一些“更改消息”通信。

英文:

There is no AWT or Swing way to get the Excel-XML (or binary) data. Also see this JDK Enhancement-Ticket from the year 2013.

You could use JavaFX, SWT or the "Windows-Only" native Win32 API via JNA. The Clipboard-Documentation from Microsoft helped me a lot:

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinDef.BOOL;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.UINT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.win32.StdCallLibrary;
/**
* Shows the Excel-XML-clipboard content on Windows. Be sure to select some
* cells in Excel and copy them with &quot;Ctrl+C&quot;.
* 
* @author bobndrew
*/
public class WindowsSystemClipboardAccess {
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary(&quot;user32&quot;, User32.class);
int CountClipboardFormats();
UINT RegisterClipboardFormatA(String lpszFormat);
BOOL OpenClipboard(HWND hWndNewOwner);
BOOL CloseClipboard();
HANDLE GetClipboardData(UINT uFormat);
DWORD GetLastError();
}
public static void main(String args[]) throws Exception {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
System.out.println(&quot;There are &quot; + clipboard.getAvailableDataFlavors().length
+ &quot; data flavors, but all are leading to a plainText- or htmlText-representation of the clipboard content:&quot;);
for (DataFlavor flavor : clipboard.getAvailableDataFlavors()) {
System.out.println(flavor.getHumanPresentableName() + &quot;\t&quot; + flavor);
}
System.out.println(&quot;\n\nSo we are using JNA to call the windows-API. The number of Windows-ClipboardFormats is &quot;
+ User32.INSTANCE.CountClipboardFormats() + &quot;.&quot;);
UINT formatNumber = User32.INSTANCE.RegisterClipboardFormatA(&quot;XML Spreadsheet&quot;);
System.out.println(formatNumber);
System.out.println(User32.INSTANCE.OpenClipboard(null));
HANDLE xmlData = User32.INSTANCE.GetClipboardData(formatNumber);
System.out.println(xmlData);
System.out.println(Kernel32.INSTANCE.GetLastError());
System.out.println(Native.getLastError());
System.out.println(User32.INSTANCE.CloseClipboard());
System.out.println(&quot;\n&quot; + xmlData.getPointer().getString(0));
}
}

The last line oft this SSCCE example produces xml like this:

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;?mso-application progid=&quot;Excel.Sheet&quot;?&gt;
&lt;Workbook xmlns=&quot;urn:schemas-microsoft-com:office:spreadsheet&quot;
xmlns:o=&quot;urn:schemas-microsoft-com:office:office&quot;
xmlns:x=&quot;urn:schemas-microsoft-com:office:excel&quot;
xmlns:ss=&quot;urn:schemas-microsoft-com:office:spreadsheet&quot;
xmlns:html=&quot;http://www.w3.org/TR/REC-html40&quot;&gt;
&lt;Styles&gt;
&lt;Style ss:ID=&quot;Default&quot; ss:Name=&quot;Normal&quot;&gt;
&lt;Alignment ss:Vertical=&quot;Bottom&quot;/&gt;
&lt;Borders/&gt;
&lt;Font ss:FontName=&quot;Calibri&quot; x:Family=&quot;Swiss&quot; ss:Size=&quot;11&quot; ss:Color=&quot;#000000&quot;/&gt;
&lt;Interior/&gt;
&lt;NumberFormat/&gt;
&lt;Protection/&gt;
&lt;/Style&gt;
&lt;/Styles&gt;
&lt;Worksheet ss:Name=&quot;Tabelle1&quot;&gt;
&lt;Table ss:ExpandedColumnCount=&quot;4&quot; ss:ExpandedRowCount=&quot;4&quot;
ss:DefaultColumnWidth=&quot;62.400000000000006&quot; ss:DefaultRowHeight=&quot;14.4&quot;&gt;
&lt;Row&gt;
&lt;Cell ss:Index=&quot;2&quot;&gt;&lt;Data ss:Type=&quot;Number&quot;&gt;1.2&lt;/Data&gt;&lt;/Cell&gt;
&lt;Cell&gt;&lt;Data ss:Type=&quot;Number&quot;&gt;123&lt;/Data&gt;&lt;/Cell&gt;
&lt;/Row&gt;
&lt;Row&gt;
&lt;Cell ss:Index=&quot;2&quot;&gt;&lt;Data ss:Type=&quot;String&quot;&gt;A String with 1 Number&lt;/Data&gt;&lt;/Cell&gt;
&lt;Cell ss:Formula=&quot;=R[-1]C+R[-1]C[-1]&quot;&gt;&lt;Data ss:Type=&quot;Number&quot;&gt;124.2&lt;/Data&gt;&lt;/Cell&gt;
&lt;/Row&gt;
&lt;/Table&gt;
&lt;/Worksheet&gt;
&lt;/Workbook&gt;

If you want to co grazy there's also some "change-messaging" possible, registering your application-window in the Windows "Clipboard Viewer Chain".

huangapple
  • 本文由 发表于 2020年8月4日 20:21:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63246773.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定