Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 如何从Excal调用Oracle打包函数_Excel_Oracle_Vba_Stored Procedures - Fatal编程技术网

Excel 如何从Excal调用Oracle打包函数

Excel 如何从Excal调用Oracle打包函数,excel,oracle,vba,stored-procedures,Excel,Oracle,Vba,Stored Procedures,我正在尝试在Oracle 11g数据库中执行一个包和函数。 我有以下代码,但是,我在第一个.Execute命令中得到一个错误 VBA中的“局部变量”窗口提供了有关错误的以下信息: Description : "Unspecified error" : String Number : -2147467259 : Long Source : "OraOLEDB" : String 哦,我引用了Microsoft ActiveX数据对象6.1库 我尝试过对代码进行各种更改,但是它们都返回相同的错误消

我正在尝试在Oracle 11g数据库中执行一个包和函数。 我有以下代码,但是,我在第一个.Execute命令中得到一个错误

VBA中的“局部变量”窗口提供了有关错误的以下信息:

Description : "Unspecified error" : String
Number : -2147467259 : Long
Source : "OraOLEDB" : String
哦,我引用了Microsoft ActiveX数据对象6.1库

我尝试过对代码进行各种更改,但是它们都返回相同的错误消息

Sub QueryGLComb()

Dim OraCon As ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim objErr As ADODB.Error
Dim lngRow As Long

On Error GoTo err_test

Set OraCon = CreateObject("ADODB.Connection")
OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
                          "Data Source=DEMO;" & _
                          "User ID=scott;" & _
                          "Password=tiger;"
OraCon.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon

If OraCon.State = adStateClosed Then
    MsgBox "false"
End If

With cmd
  .ActiveConnection = OraCon
  .CommandText = "fnd_flex_keyval.validate_segs"
  .CommandType = adCmdStoredProc
  .CommandTimeout = 60
  .Parameters.Append .CreateParameter("return", adBoolean, adParamReturnValue)
  .Parameters.Append .CreateParameter("operation", adVariant, adParamInput, , "CHECK_COMBINATION")
  .Parameters.Append .CreateParameter("appl_short_name", adVariant, adParamInput, , "SQLGL")
  .Parameters.Append .CreateParameter("key_flex_code", adVariant, adParamInput, , "GL#")
  .Parameters.Append .CreateParameter("structure_number", adNumeric, adParamInput, , "50268")
  .Parameters.Append .CreateParameter("concat_segments", adVariant, adParamInput, , "67000.2400.4001.01")
  .Parameters.Append .CreateParameter("validation_date", adVariant, adParamInput, , "sysdate")
  .Execute
End With

Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon
With cmd
  .ActiveConnection = OraCon
  .CommandText = "begin FND_FLEX_KEYVAL.ERROR_MESSAGE"
  .CommandType = adCmdStoredProc
  .Parameters.Append .CreateParameter("message", adVariant, adParamReturnValue)
  .Execute
End With

MsgBox "Return Message = " & cmd.Parameters(0)

OraCon.Close

err_test:
    MsgBox Error$
    For Each objErr In OraCon.Errors
        MsgBox objErr.Description
    Next
    OraCon.Errors.Clear
    Resume Next

End Sub
DECLARE
    l_return  boolean;
    l_message varchar2(240); 
BEGIN
    l_return := fnd_flex_keyval.validate_segs(operation => 'CHECK_COMBINATION'
                                           ,appl_short_name => 'SQLGL'
                                           ,key_flex_code => 'GL#'
                                           ,structure_number => 50268 --- Pass your chart of accounts id
                                           ,concat_segments => '67000.2400.4001.01' --- Pass your account combination string you want to create
                                           ,validation_date => sysdate); --- effective date by which you want the combination to be validated

   l_message := FND_FLEX_KEYVAL.ERROR_MESSAGE;
    If l_return THEN
        dbms_output.put_line('Valid');
    Else
        dbms_output.put_line(l_message);
    End if;
END;
第一个.Execute行是发生错误的地方

下面是我在SQLDeveloper/Toad中使用的Oracle代码。我调用的包是FND\u FLEX\u VALIDATE,函数是VALIDATE\u SEGS。这是Oracle eBS中Oracle提供的软件包。如果对fnd_flex_keyval.validate_segs的初始调用返回true,则一切正常。如果它返回错误,那么我们必须调用FND_FLEX_KEYVAL.error_MESSAGE来检索错误消息

Sub QueryGLComb()

Dim OraCon As ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim objErr As ADODB.Error
Dim lngRow As Long

On Error GoTo err_test

Set OraCon = CreateObject("ADODB.Connection")
OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
                          "Data Source=DEMO;" & _
                          "User ID=scott;" & _
                          "Password=tiger;"
OraCon.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon

If OraCon.State = adStateClosed Then
    MsgBox "false"
End If

With cmd
  .ActiveConnection = OraCon
  .CommandText = "fnd_flex_keyval.validate_segs"
  .CommandType = adCmdStoredProc
  .CommandTimeout = 60
  .Parameters.Append .CreateParameter("return", adBoolean, adParamReturnValue)
  .Parameters.Append .CreateParameter("operation", adVariant, adParamInput, , "CHECK_COMBINATION")
  .Parameters.Append .CreateParameter("appl_short_name", adVariant, adParamInput, , "SQLGL")
  .Parameters.Append .CreateParameter("key_flex_code", adVariant, adParamInput, , "GL#")
  .Parameters.Append .CreateParameter("structure_number", adNumeric, adParamInput, , "50268")
  .Parameters.Append .CreateParameter("concat_segments", adVariant, adParamInput, , "67000.2400.4001.01")
  .Parameters.Append .CreateParameter("validation_date", adVariant, adParamInput, , "sysdate")
  .Execute
End With

Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon
With cmd
  .ActiveConnection = OraCon
  .CommandText = "begin FND_FLEX_KEYVAL.ERROR_MESSAGE"
  .CommandType = adCmdStoredProc
  .Parameters.Append .CreateParameter("message", adVariant, adParamReturnValue)
  .Execute
End With

MsgBox "Return Message = " & cmd.Parameters(0)

OraCon.Close

err_test:
    MsgBox Error$
    For Each objErr In OraCon.Errors
        MsgBox objErr.Description
    Next
    OraCon.Errors.Clear
    Resume Next

End Sub
DECLARE
    l_return  boolean;
    l_message varchar2(240); 
BEGIN
    l_return := fnd_flex_keyval.validate_segs(operation => 'CHECK_COMBINATION'
                                           ,appl_short_name => 'SQLGL'
                                           ,key_flex_code => 'GL#'
                                           ,structure_number => 50268 --- Pass your chart of accounts id
                                           ,concat_segments => '67000.2400.4001.01' --- Pass your account combination string you want to create
                                           ,validation_date => sysdate); --- effective date by which you want the combination to be validated

   l_message := FND_FLEX_KEYVAL.ERROR_MESSAGE;
    If l_return THEN
        dbms_output.put_line('Valid');
    Else
        dbms_output.put_line(l_message);
    End if;
END;
我已经创建了一个新文件进行测试。我现在尝试执行的过程有3个参数:1 in,2 out。同样,当代码到达.Execute命令时,我仍然收到相同的错误

Sub ExecutePackageP()

Dim OraCon As New ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command
Dim objErr As ADODB.Error
Dim lngRow As Long

On Error GoTo err_test

Set OraCon = CreateObject("ADODB.Connection")

OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
                          "Data Source=demo;" & _
                          "User ID=scott;" & _
                          "Password=tiger;"
OraCon.Open
cmd.ActiveConnection = OraCon

If OraCon.State = adStateClosed Then
    MsgBox "false"
End If

With cmd
    .ActiveConnection = OraCon
    .CommandType = adCmdStoredProc
    .CommandText = "XXX_VALIDATE_ACCOUNT"
    .CommandTimeout = 60
    .Parameters.Append .CreateParameter("param1", adVariant, adParamInput, , "67000.2400.4001.01")
    .Parameters.Append .CreateParameter("param2", adBoolean, adParamOutput)
    .Parameters.Append .CreateParameter("param3", adVariant, adParamOutput)
    .Execute
End With

MsgBox "Reurtn = P_CCID=" & cmd.Parameters(1) & "; P_RESULT=" & cmd.Parameters(2) & ";"

OraCon.Close
End sub
我将参数类型从adVariant更改为adVarchar,并收到一条错误消息,指出参数对象定义不正确。只有adVariant似乎有效。我记得有一个网站展示了对不同数据库执行时要使用的类型,它说varchar2使用adVariant。 为xxx\u validate\u帐户添加过程代码:注意,此过程调用名为fnd\u flex\u ext.get\u ccid的内部oracle函数

CREATE OR REPLACE PROCEDURE APPS."XXX_VALIDATE_ACCOUNT" (p_account_flex in varchar2,
                         p_valid out boolean,
                         p_message out varchar2) is

x_structure_id number;
x_ccid number := 0;

pragma autonomous_transaction;

begin

execute immediate 'alter session set nls_language = ''AMERICAN''';

p_valid := false;

select chart_of_accounts_id
into x_structure_id
from gl_ledgers
where short_name = 'XXX';

x_ccid := fnd_flex_ext.get_ccid(application_short_name => 'SQLGL',
                        key_flex_code => 'GL#',
                        structure_number => x_structure_id,
                        validation_date => to_char(sysdate,'YYYY/MM/DD HH24:MI:SS'),
                        concatenated_segments => p_account_flex);

if x_ccid > 0 then
    p_valid := true;
    commit;
else
    p_valid := false;
    p_message := fnd_message.get;
end if;

exception when others then
        p_message := sqlerrm;
        p_valid := false;

end xxx_validate_account;
/
更新:2015年9月25日: 不幸的是,我无法更新该软件包,因为其他软件包和应用程序正在使用它。 因此,我决定创建一个具有简单函数的新包。 我确保输入和输出不是布尔型的,因此无法解决这个问题。 然而,就我的一生而言,我仍然会遇到同样的问题! 我试图在参数字符串中使用adVarchar,100,但是excel一直告诉我参数的类型是错误的。认真考虑我的机器有什么问题

要遵循的新功能和代码:

create or replace package apps.xxxx_return_username is 
function return_username (p_user_id in number) return varchar2;
end xxxx_return_username;
/
create or replace package body apps.xxxx_return_username as
function return_username(p_user_id in number) return varchar2 is
x_user_name varchar2(100);
begin
select user_name into x_user_name
from apps.fnd_user where user_id = p_user_id;
return x_user_name;
exception
  when no_data_found then return 'xxxxx';
end return_username;
end xxxx_return_username;
/


Sub newfunctioncall()

Dim OraCon As New ADODB.Connection
Dim recset As New ADODB.Recordset
Dim cmd As New ADODB.Command

Set OraCon = CreateObject("ADODB.Connection")

OraCon.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
                          "Data Source=demo;" & _
                          "User ID=scott;" & _
                          "Password=tiger;"
OraCon.Open
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = OraCon

If OraCon.State = adStateClosed Then
    MsgBox "false"
End If

Set param1 = cmd.CreateParameter("param1", adNumeric, adParamInput, , "15483")
cmd.Parameters.Append param1
Set param2 = cmd.CreateParameter("param2", adVariant, , adParamReturnValue)
cmd.Parameters.Append param2

cmd.CommandType = adCmdStoredProc
cmd.CommandText = "xxecu_return_username.return_username"
Set recset = cmd.Execute

MsgBox "Reurtn = USERNAME=" & cmd.Parameters(0)

OraCon.Close

End Sub

如何知道您正在Oracle数据库中执行有效的命令?您可能希望首先使用SQLplus进行尝试。不太知道函数调用在哪里。可能是:

begin FND_FLEX_KEYVAL.ERROR_MESSAGE
但这并不是一个完整的声明。至少它需要以下几点

begin 
   FND_FLEX_KEYVAL.ERROR_MESSAGE; 
end;
但是,如果FND_FLEX_KEYVAL.ERROR_消息是一个函数,那么前面的代码也不会运行。在这种情况下,您需要选择函数值:

select FND_FLEX_KEYVAL.ERROR_MESSAGE from dual

很好地描述了问题的背景

我看到了一些可能出现问题的地方。在不知道具体是哪一种情况下,我认为这是一个工作代码的示例,它可以实现您所寻求的功能-尽管我承认我可能有一些错误

首先,在您的过程中,如果您将变量声明为参数:

create or replace procedure validate_segs(
  operation in varchar2,
  appl_short_name in varchar2,
  key_flex_code in varchar2,
  structure_number in number,
  concat_segments in varchar2,
  validation_date in date,
  message out varchar2,
  results out numeric
) as
BEGIN
  message := 'Hello';
  results := 1;
END;
然后,在VBA中,我认为您可以这样做。有了VBA/OleDB和Oracle,我从来没有让布尔人表现出来。它们在C中工作得很好,但我在VBA中没有成功,所以我在本例中将其转换为一个数字,在VBA中它似乎总是转换为布尔值

With cmd
  .ActiveConnection = OraCon
  .CommandText = "validate_segs"
  .CommandType = adCmdStoredProc
  .CommandTimeout = 60
  .NamedParameters = True

  .Parameters.Append .CreateParameter( _
      "operation", adVarChar, adParamInput, 255, "CHECK_COMBINATION")
  .Parameters.Append .CreateParameter( _
      "appl_short_name", adVarChar, adParamInput, 255, "SQLGL")
  .Parameters.Append .CreateParameter( _
      "key_flex_code", adVarChar, adParamInput, 255, "GL#")
  .Parameters.Append .CreateParameter( _
      "structure_number", adNumeric, adParamInput, 10, 50268)
  .Parameters.Append .CreateParameter( _
      "concat_segments", adVarChar, adParamInput, 255, "67000.2400.4001.01")
  .Parameters.Append .CreateParameter( _
      "validation_date", adDate, adParamInput, , Now())
  .Parameters.Append .CreateParameter("message", adVarChar, adParamOutput, 255)
  .Parameters.Append .CreateParameter("return", adNumeric, adParamOutput, 1)
  .Execute
End With
然后,要从存储过程中实际挖掘结果:

Dim result As Boolean
Dim message As String

message = cmd.Parameters(6).Value
result = cmd.Parameters(7).Value
我意识到您可能被锁定在VBA中,但很可能您有选择,.NET的接口为调试这类事情提供了更好的环境

-2015年9月24日编辑-

我认为你的代码就快到了,但是我可以看到还有两个问题,其中一个我不是100%确定是不是一个问题,但我认为另一个是。我之前在解决方案中没有提到这一点,但我现在认为这可能是核心问题:OLEDB和Oracle Boolean似乎不能很好地结合在一起。见本文:

要解决这个问题,如果您在Oracle和VBA中将其切换到一个数字,它应该可以工作

另一个问题,我不确定是不是真的,就是在我认为应该使用string或Varchar Db类型时,您正在使用Variant Db类型。您提到您在文档中看到要使用变体,所以这可能无关紧要。。。但是Varchar会起作用的。您确实需要文本长度的附加参数,以便正确编译。我使用255作为kicks

因此,我建议的两个变化是:

1在存储过程中从布尔值更改为数字:

CREATE OR REPLACE PROCEDURE "XXX_VALIDATE_ACCOUNT" (
   p_account_flex in varchar2, p_valid out number, p_message out varchar2) is
      -- blah blah blah
   p_valid := 0;
2更改VBA代码以期望返回一个数字,并将变量转换为Varchar

.Parameters.Append .CreateParameter("param1", adVarChar, adParamInput, 255, _
    "67000.2400.4001.01")
.Parameters.Append .CreateParameter("param2", adNumeric, adParamOutput)
.Parameters.Append .CreateParameter("param3", adVarChar, adParamOutput, 255)
即使您将其转换为布尔值

Dim result As Boolean
result = cmd.Parameters(1).Value

我必须说,调试器返回的错误消息对此毫无帮助。

如果您在错误上注释掉哪一行引发了错误?嗨,蒂姆。第一个.Execute行是发生错误的地方。您可以为XXX\u VALIDATE\u帐户添加代码吗?另外,我在回答中建议的一个变化是从adVariant转换为实际的数据类型,在大多数情况下,它是adVarchar。我只是有一个想法。我使用的是32位Excel,但使用的是64位instal Oracle客户端
带路。这可能是个问题吗?我不确定是否可以同时安装32和64个客户端,然后以某种方式选择在excel中使用哪一个。然而,我只是想。在同一个工作簿中,我有一个宏,可以对同一个数据库执行简单的sql查询,并且100%有效。所以现在我想这可能不是一个司机的问题。谢谢你的回复。我已经设置了一个新文件,尝试连接到Oracle,以针对不同的过程进行测试。此过程有一个1输入作为varchar2,2输出,1为布尔值,1为varchar2。我已经在我的原始问题中加入了新代码。