0

我正在尝试使用 TOpenDialog 将所选文件的路径传递给 AdoConection 并将 Excel 文件的内容加载到表中。我目前正在尝试下面的代码,但代码的最后一部分没有连接到 Excel,返回错误: [dcc32 Error] sample_map.pas(80): E2010 Incompatible types: 'string' and 'TOpenDialog'

procedure TForm1.Button1Click(Sender: TObject);
var
  openDialog : TOpenDialog;    // Open dialog variable
  strConn : WideString; // Declare wide string for the connection

begin
  // Create the open dialog object - assign to our open dialog variable
  openDialog := TOpenDialog.Create(self);

  // Set up the starting directory to be the current one
  openDialog.InitialDir := GetCurrentDir;

  // Only allow existing files to be selected
  openDialog.Options := [ofFileMustExist];

  // Allow only .dpr and .pas files to be selected
  openDialog.Filter :=
    'Excel 2003 and older|*.xls|Excel 2007 and older|*.xlsx';

  // Select pascal files as the starting filter type
  openDialog.FilterIndex := 2;

  // Display the open file dialog
  if openDialog.Execute
  then ShowMessage('File : '+openDialog.FileName)
  else ShowMessage('Open file was cancelled');

  // Free up the dialog
  openDialog.Free;

  // Connect the Excel file
    strConn:='Provider=Microsoft.Jet.OLEDB.4.0;' +
                 'Data Source=' + openDialog + ';' +
                 'Extended Properties=Excel 8.0;';
        AdoConnection1.Connected:=False;
        AdoConnection1.ConnectionString:=strConn;
end;
4

2 回答 2

4

openDialog是文件对话框的一个实例。它不是一个字符串。您需要FileName像这样读取文件对话框对象的属性:

openDialog.FileName

事实上,你已经在你的一个ShowMessage电话中使用了它。

请确保在调用之前阅读此属性Free,问题中的代码中存在错误。

事实上,你确实需要养成使用try/finally保护资源的习惯。任何时候你创建一个类的实例,你都需要确保即使在遇到异常时它也会被销毁。在您的代码中,您需要这样编写:

openDialog := TOpenDialog.Create(self);
try
  .... // use openDialog to let user choose file:
  strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
             'Data Source=' + openDialog.FileName + ';' +
             'Extended Properties=Excel 8.0;';
finally
  openDialog.Free; // executes no matter what, even if exception raised, etc.
end;

我也不认为你需要在WideString这里使用。如果您使用 Unicode Delphi,那么您可以使用本机string类型,它是UnicodeString. 如果您的 Delphi 是 pre-Unicode,那么您也可以安全地使用string,这种情况下的别名AnsiString。您使用的文字是 ASCII。文件对话框是 ANSI 控件,openDialog.FileNameANSI 也是。使用WideString.

最后,您正在混合一个功能、选择文件名的代码和处理数据库连接的代码。最好将关注点分开。创建一个简单地返回文件名的方法,该文件名是通过让用户通过对话框进行选择而获得的。并添加一个方法来处理数据库连接,即传递一个文件名作为参数。

于 2014-06-27T08:24:51.450 回答
4

You need to get the OpenDialog.FileName prior to freeing the dialog:

OpenDialog := TOpenDialog.Create(nil);
try
  // Set up the OpenDialog as before

  // Display the open file dialog
  if openDialog.Execute then
  begin
    strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
               'Data Source=' + openDialog.FileName + ';' +
               'Extended Properties=Excel 8.0;';
    // Connect the Excel file
    AdoConnection1.Connected:=False;
    AdoConnection1.ConnectionString:=strConn;
  else 
    ShowMessage('Open file was cancelled');
finally
  // Free up the dialog
  openDialog.Free;
end;

Of course, you're working much too hard. The Dialogs unit has a much easier way to do this using the PromptForFilename function, which eliminates the need to create and free the dialog entirely:

var
  FileName: string;
begin

  FileName := '';
  if PromptForFileName(FileName,                          // Chosen filename holder
                      'Excel 2003 and older|*.xls|Excel 2007 and older|*.xlsx';  // Filter(s) (optional)
                      '.xlsx',                            // Default extension (opt)
                      'Choose file',                     // Dialog title (opt)
                      GetCurrentDir,                     // Initial dir (opt)
                      False) then                        // Is it a save dlg? (opt)
  begin
    strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
               'Data Source=' + FileName + ';' +
               'Extended Properties=Excel 8.0;';
    // Connect the Excel file
    AdoConnection1.Connected:=False;
    AdoConnection1.ConnectionString:=strConn;
  end
  else
    ShowMessage('Dialog cancelled.');
end;

As a side note, in case you don't know: You can select all Excel files (both .xls and .xlsx) with a single filter if you enter it as .xls*, as in Excel Files|*.xls*.

And, as David says, the best way would be to separate out the code that gets the filename and the code that does the connection as separate functions. Call the first to get the filename, and then pass that filename to the second to actually do the connecting if a filename is selected.

于 2014-06-27T12:49:51.770 回答