如何从java中的Excel工作表中动态更改值而不保存Excel工作表

时间:2018-05-26 07:57:53

标签: java excel distributed-system quantitative-finance algorithmic-trading

我正在使用Nest Trader应用程序(与股票市场交易相关),它在Excel工作表中提供值,并以毫秒为单位快速更新单元格中的值。

我想读取这些值并将它们保存在数据库中 我正在使用apache poi-3.17库。

2 个答案:

答案 0 :(得分:1)

  

如何在不保存Excel工作表的情况下从Java中的Excel工作表中动态更改值?

如果到目前为止没有实现,可以使用 JDDE - 图书馆,详情如下。

毫秒是充足的时间......

在普通的交易环境中(即使还没有谈到即使是低端的HFT),所有纳秒 [ns] 延迟都会被策划,最好避免,不要添加太多 [us] ,所以[ms]确实有足够的时间 - 但仍然值得将任何天真的实现卸载到主要的“远程”端,因为这既“导出”这样的工作量(不是花费你平台上的关键时间)+它也避免了链式延迟,因为决策是在尽可能短的时间内做出的(并且下一次广告仅在案例中,与您的平台部分相关。)

可以重复使用:

JDDE是基于JNI的免费开源Java库,它允许Java应用程序与Windows平台上的本机应用程序进行通信(如果这些仍然允许) - 在Vista64中遇到问题,但这超出了这篇文章的范围)通过 D ynamic D ata E xchange(又名DDE)协议。

一个粗暴的DDE力量示例:

作为使用某种暴力的示例,下面的代码将使用Java应用程序中正在运行的Microsoft Excel设置DDE连接。

另一种更聪明的方式,如果Excel-DDE实施在2018年仍然支持这一点,那就是订阅“受监控”内容的所有变化(因为这更接近于交易生态系统和REUTERS系统早在199x使用它,即使在几天内,Windows O / S还没有配备基于TCP / IP的网络,那些日子已经使用DDE了:o)

天真 - 暴力 - DDE力例子执行:
- 从REQUEST - 单元格中读取数据的 A1 操作,这是本主题的主题
+ POKE操作来更改A1单元格中的数据,以及
+ EXECUTE关闭Excel文档的操作,如果需要用于其他用例。

 /*
 * Copyright 2009 www.pretty-tools.com. All rights reserved.
 */

import com.pretty_tools.dde.ClipboardFormat;
import com.pretty_tools.dde.DDEException;
import com.pretty_tools.dde.DDEMLException;
import com.pretty_tools.dde.client.DDEClientConversation;

/**
 * Excel Example.
 *
 * @author Alexander Kozlov
 */

public class ExcelExample
{
    public static void main( String[] args )
    {
        try
        {
                         //                                DDE client
            final DDEClientConversation conversation = new DDEClientConversation();
                         //                     We can use UNICODE format if server prefers it
         // conversation.setTextFormat( ClipboardFormat.CF_UNICODETEXT );

            conversation.setTimeout( 3000 );
                         //                     Establish conversation with opened and active workbook
            conversation.connect( "Excel", "Sheet1" );
                         //                     if you have several opened files,
                         //                        you can establish conversation using file path
         // conversation.connect( "Excel", "C:\\Book1.xlsx" );
                         //                     or you can also specify Sheet
         // conversation.connect( "Excel", "C:\\[Book1.xlsx]Sheet2" );
            try
            {
                             //                  Requesting A1 value
                System.out.println( "A1 value: " + conversation.request( "R1C1" ) );
                             //                  Changing cell A1 value to "We did it!"
                conversation.poke( "R1C1", "We did it!" );
                conversation.poke( "R2C2", "We did it again!".getBytes(), ClipboardFormat.CF_TEXT );
                             //                  Fill several cells of the same row,
                             //                       using \t as separator
                conversation.poke( "R4", "Fill\tthe\trow" );
                             //                  Fill several cells of the same column,
                             //                       using \n as separator
                conversation.poke( "C4", "Fill\nthe\ncolumn" );
                             //                  Fill several cells with matrix,
                             //                       using \t as column separator
                             //                         and \n as row separator
                conversation.poke( "R5C5:R7C7", "1\t2\t3\n4\t5\t6\n7\t8\t9" );
                             //                  Run macro with name Macro1
             // conversation.execute( "[run(\"Macro1\")]" );
                             //                  Sending "close()" command
                conversation.execute( "[close()]" );
                             //                  or we can use byte array to send command
             // conversation.execute( "[close()]\0".getBytes() );
            }
            finally
            {
                conversation.disconnect();
            }
        }
        catch ( DDEMLException e )
        {
            System.out.println( "DDEMLException: 0x"
                              +  Integer.toHexString( e.getErrorCode() )
                              + " "
                              +  e.getMessage()
                                 );
        }
        catch ( DDEException e )
        {
            System.out.println( "DDEClientException: "
                              +  e.getMessage()
                                 );
        }
        catch ( Exception e )
        {
            System.out.println( "Exception: "
                              +  e
                                 );
        }
    }
}

SMART-er方式的一种方式 - 避免“手动”轮询+卸载到DDE自我广告的变更监视器/传播者:

以下示例侦听Excel单元格中的更改。 .setEventListener() 方法用于设置异步事件处理程序(代理,在中工作以侦听远程事件并负责 - 一旦收到任何此类事件 - 对于本地方面,对此类事件的响应反应,以及其他事件。

在这个简单的模拟演示中,它只会将任何远程 A1 - 单元更改打印到此Java应用程序的本地控制台(并处理断开事件,显然类似重要的一步):

/*
 * Copyright 2009 www.pretty-tools.com. All rights reserved.
 */

import com.pretty_tools.dde.DDEException;
import com.pretty_tools.dde.client.DDEClientConversation;
import com.pretty_tools.dde.client.DDEClientEventListener;
import com.pretty_tools.dde.DDEMLException;

/**
 * Excel Advice Example.
 *
 * @author Alexander Kozlov
 */

public class ExcelAdviceExample
{
    public static void main( String[] args )
    {
        try
        {
                         //                                DDE client
            final DDEClientConversation conversation = new DDEClientConversation();
                         //                     We can use UNICODE format if server prefers it
         // conversation.setTextFormat( ClipboardFormat.CF_UNICODETEXT );

            conversation.setEventListener( new DDEClientEventListener()
            {
                public void onDisconnect()
                {
                    System.out.println( "onDisconnect()" );
                }

                public void onItemChanged( String topic, String item, String data )
                {
                    System.out.println( "onItemChanged( "
                                      +  topic
                                      + ","
                                      +  item
                                      + ","
                                      +  data.trim()
                                      + ")"
                                         );
                }
            } );

            System.out.println(            "Connecting..." );
            conversation.connect( "Excel", "Sheet1" );
            try
            {            // .startAdvice(-------------------------------
                conversation.startAdvice(  "R1C1" );

                System.out.println(        "Press Enter to quit" );
                System.in.read();

                conversation.stopAdvice(   "R1C1" );
            }            // .stopAdvice(--------------------------------
            finally
            {
                conversation.disconnect();
            }
        }
        catch ( DDEMLException e )
        {
            System.out.println( "DDEMLException: 0x"
                              +  Integer.toHexString( e.getErrorCode() )
                              + " "
                              +  e.getMessage()
                                 );
        }
        catch ( DDEException e )
        {
            System.out.println( "DDEClientException: "
                              +  e.getMessage()
                                 );
        }
        catch ( Exception e )
        {
            System.out.println( "Exception: "
                              +  e
                                 );
        }
    }
}

JDDE是基于JNI的库,它需要本机代码库(适用于Windows的DLL)。

因此,DLL(一个 == JavaDDE.dll 文件)应放在您运行示例的当前目录中,或者您应该指定JVM java.library.path,该参数指向到存储JavaDDE.dll文件的文件夹。

示例:

 java -Djava.library.path="C:\jdde" ExcelExample

答案 1 :(得分:0)

如果您只能在Excel中获取值,则可以编写工作表函数(UDF)来获取值并将其写入数据库。

您可以使用Jinx https://exceljava.com用Java编写Excel工作表函数。