回 帖 发 新 帖 刷新版面

主题:[原创]实现在fortran 中调用数据库和电子表格读写的理想方法

实现在fortran 中调用数据库和电子表格读写的理想方法


感谢这段时间里 编成爱好者fortran版的各位热心的老师给予我无私的帮助!!

我以前只是简单的学习了一些c语言的内容,对程序一直不是太懂。只是因为毕业设计的原应才与两个月前开始学习fortran。我毕设的内容是要模拟理想的电力市场,并且预测发电厂的发电量和电力市场里面其他的量,里面关于计算的部分已经存在了,我要做的就是让fortran 从数据库里进行读写数据,这样是便于和java 结合,使得可以让用户从网上实时输入数据。

    我开始一直以为fortran 不能从数据库里读写数据的,而且网上也有相似的问题,但并没有答案,或者说是实现不了。所以我就准备将已由的程序编译成dll文件,让C++调用。但也有的程序太多了,而且在c++里调用数据库网上提到比较多的就是mfc方法,这样的话或产生界面,而我是不需要界面(界面会有java处理),在win32用c++直接调用数据库我有没有找到具体的例子。(大家有的话可以提供给我,谢谢了)

   这时候我都准备放弃了,还好,在编成网上有人提出了用f90SQL可以。 

   然后我就在实验室的机子上开始尝试,刚开始时用cvf6.5 的,好像感觉并不是很行。实验室刚好这个时候新买了ivf9.1 ,幸运的是f90SQl在那个上面可以,直到这个时候我的毕设才真正的开始,在大家的帮助下,我进展的很快,现在已经差不多完成了。

我想把我在编成的一些经验和问题提出来,和大家一起分享一下:)


首先fortran是可以在数据库和电子表之间进行读写的。而且数据库与电子表的操作完全是一样的

1    调用F90SQL, 
http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/117268.aspx
这里可以免费下载f90SQL-lite版
安装:
复制f90SQL library (f90SQL.lib) 到fortran compiler 的LIB路径下, 我是直接在编译路径里面添加的。
复制  f90SQL dynamic link library (f90SQLxxx.DLL) (共2个)到系统目录下,如:WinNT\SYSTEM32 in Windows NT
       复制f90SQL modules (f90SQL.f90, f90SQL.mod,共6个) 到fortran compiler 的include/module路径下,我是直接在编译路径里面添加的。


之后就可以调用f90SQL语言进行数据库操作了。 因为使用的是lite版,所以数据库在使用前必须先到Data Sources (ODBC) 里面注册,另外数据库必须是2003或以前的,不支持2007(已测试过)

选用的是access database 和excel表格

从数据库中读取数据:

program main



!load f90SQL modules
use f90SQLConstants
use f90SQL

implicit none

integer(SQLHENV_KIND)::    EnvHndl
integer(SQLHDBC_KIND)::    ConnHndl
integer(SQLHSTMT_KIND)::   StmtHndl
integer(SQLRETURN_KIND)::  iRet
character(len=20)::             AuthorsStr
integer::                  i


!allocate an environment handle
call f90SQLAllocHandle(SQL_HANDLE_ENV, 0, EnvHndl, iRet)

!Set ODBC version, we will be using 3.x in this case
call f90SQLSetEnvAttr(EnvHndl, SQL_ATTR_ODBC_VERSION, &
                      SQL_OV_ODBC3, iRet)

!Allocate a connection handle
call f90SQLAllocHandle(SQL_HANDLE_DBC,EnvHndl, ConnHndl, iRet)

!Open DSN input
call f90SQLConnect(ConnHndl,'input','Admin','',iRet)  ! 数据库DSN名字为input

if (iRet.eq.SQL_SUCCESS .or. iRet.eq.SQL_SUCCESS_WITH_INFO) then

    !Allocate statement handdle
    call f90SQLAllocHandle(SQL_HANDLE_STMT,ConnHndl, StmtHndl, iRet)

    if (iRet.eq.SQL_SUCCESS .or. iRet.eq.SQL_SUCCESS_WITH_INFO) then

        !Bind AuthorStr variable to the only column returned by SQL stmt
        call f90SQLBindCol(StmtHndl,int(1,SQLSMALLINT_KIND),SQL_F_CHAR, &
                           AuthorsStr,0,iRet)

        !Instruct driver to execute statement
        call f90SQLExecDirect(StmtHndl,'SELECT TOP 10 Author from Authors',iRet) !sql的调用语句,Authors为其中的一个表,Author为该表中的栏

        print *,'Name of first 10 authors in input database'

        !loop through result set and print results to screen
        do i=1, 10
            call f90SQLFetch(StmtHndl, iRet)
            if (iRet.ne.SQL_SUCCESS .and. iRet.ne.SQL_SUCCESS_WITH_INFO) &
                exit
            !reformat string in AuthorsStr to make it fortran-compatible
            call f90SQLStrFormat(AuthorsStr,AuthorsStr) 
            !print authors
            print *, i, ' ', trim(AuthorsStr)
        enddo

    else

        print *,'Error preparing SQL statement'
        call ShowDiags(SQL_HANDLE_STMT,StmtHndl)

    endif

    !release statement handle
    call f90SQLFreeHandle(SQL_HANDLE_STMT, StmtHndl, iRet)

    !disconnect
    call f90SQLDisconnect(ConnHndl,iRet)

else
 
   print *,'Error connecting to data source'
   call ShowDiags(SQL_HANDLE_DBC,ConnHndl)

endif


!release connection handle
call f90SQLFreeHandle(SQL_HANDLE_DBC, ConnHndl, iRet)

!release environment handle
call f90SQLFreeHandle(SQL_HANDLE_ENV, EnvHndl, iRet)

stop
end



subroutine ShowDiags(HndlType,Hndl)

!This subroutine prints error diagnostics

!load f90SQL modules
use f90SQLConstants
use f90SQL

implicit none

integer(SQLHANDLE_KIND)::Hndl
integer(SQLSMALLINT_KIND)::HndlType


character(len=6):: SqlState 
character(len= SQL_MAX_MESSAGE_LENGTH)::Msg 
integer(SQLINTEGER_KIND)::NativeError 
integer(SQLSMALLINT_KIND):: iDiag, MsgLen 
integer(SQLRETURN_KIND):: DiagRet

iDiag = 1 
do while (.true.)
   call f90SQLGetDiagRec(HndlType, Hndl, iDiag, SqlState, NativeError, Msg, MsgLen, DiagRet) 
   if (DiagRet.ne.SQL_SUCCESS.and.DiagRet.ne.SQL_SUCCESS_WITH_INFO) exit 
   print *,trim(SqlState),',', NativeError,',', Msg(1:MsgLen)
   iDiag=iDiag+1 
enddo 

end subroutine ShowDiags


如果input是电子表格,只需要将call f90SQLExecDirect(StmtHndl,'SELECT TOP 10 Author from Authors',iRet)换成SELECT TOP 10 Y FROM [Sheet1$] 就可以 了(后面会贴出一个例子)

回复列表 (共25个回复)

21 楼

赞楼主的黑客精神。也赞那位用C语言举例的朋友。我也有一个想法,嘿嘿:

跟sql数据库交互最好还是编出一个客户机程序,通过mysql的服务器进程(名为mysqld_safe)来操作数据库,而不是直接读写数据库文件。但mysql有php,C接口,没有Fortran接口。

fortran2003引入一项功能叫“ISO_C_BINDING”,即与C交互。在声明后一个函数为C函数后,fortran2003源程序中可以调用。用这种方法可以让fortran程序直接与mysqld_safe进程通信,创立/删除,查询,读写数据库。

几周之内将公布的intel fortran 10.0版本将完全实现“ISO_C_BINDING”。目前的9.1版本也已经部分实现。

至于非mysql的其他数据库,可以利用mysql的强大的导入能力。

22 楼


黑客精神?[em6]

过了,没那么严重! 只是研究了一下fortran与数据库的连接问题。

现在看来这方法愈来愈多了

呵呵

23 楼

请教楼主,按照您说的方法安装了f90SQL,可是在“build”的时候总是出现如下错误:
Linking...
main.obj : error LNK2001: unresolved external symbol F90SQLALLOCHANDLE
main.obj : error LNK2001: unresolved external symbol F90SQLSETENVATTRINT
main.obj : error LNK2001: unresolved external symbol F90SQLCONNECTSTR
main.obj : error LNK2001: unresolved external symbol F90SQLBINDCOLSTR
main.obj : error LNK2001: unresolved external symbol F90SQLEXECDIRECTSTR
main.obj : error LNK2001: unresolved external symbol F90SQLFETCH

我使用的是VF6.5编译,请问该如何解决?非常感谢!!!

24 楼

回楼上,LZ的是基于IVF的~~
问个问题,odbc注册的时候为用户的dsn?
在程序中参数如何输入?
我注册了一个数据源名为test的用户dsn,链接到a.xls
但是在程序中,输入参数却有问题:
D:\>readexecl.exe
 Program ExcelRead
 Reads the 10 first rows of data from the Excel
 spreadsheet created with ExcelWrite
 Note that you must create a DSN for this Workbook
 before you can run this program. It is also possible
 to read directly from the file (without creating a DSN)
 using a similar technique to the one used in ExcelWrite
 Copyright 1998, Canaima Software

 Enter name the Data Source Name (DSN) that points to the Excel Workbook
test
 Enter your user name:
Administrator
 Enter your password (WARNING: password will show on the screen):
a1210
 Error executing SQL query
 07002

啥原因,楼主是如何注册的?

25 楼

学习学习,谢谢!!

我来回复

您尚未登录,请登录后再回复。点此登录或注册