在 Delphi 中从 TOpenDialog 将文件路径作为字符串传递

Kon*_*rad 1 delphi string widestring topendialog

我正在尝试利用 TOpenDialog 将所选文件的路径传递给 AdoConection 并将 Excel 文件的内容加载到表中。我当前正在尝试下面的代码,但代码的最后一部分未连接到 Excel,返回错误: [dcc32 Error] sample_map.pas(80): E2010 Incompile 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;
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 5

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

openDialog.FileName
Run Code Online (Sandbox Code Playgroud)

事实上,您已经在一次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;
Run Code Online (Sandbox Code Playgroud)

我也不认为你需要WideString在这里使用。如果您使用 Unicode Delphi,那么您可以使用本机string类型,它是UnicodeString. 如果您的 Delphi 是 Unicode 之前的版本,那么您也可以安全地使用string,在这种情况下的别名AnsiString。您使用的文字是 ASCII。文件对话框是 ANSI 控件,因此openDialog.FileName也是 ANSI。使用 不会有任何收获WideString

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


Ken*_*ite 5

OpenDialog.FileName您需要在释放对话框之前获取:

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;
Run Code Online (Sandbox Code Playgroud)

当然,你工作太辛苦了。该Dialogs单元有一个更简单的方法来使用该PromptForFilename函数来执行此操作,从而完全不需要创建和释放对话框:

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;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,以防您不知道:如果您输入为 ,则可以使用单个过滤器选择所有 Excel 文件(包括.xls和) ,如 中所示。.xlsx.xls*Excel Files|*.xls*

而且,正如 David 所说,最好的方法是将获取文件名的代码和执行连接的代码作为单独的函数分开。调用第一个来获取文件名,然后将该文件名传递给第二个以在选择文件名的情况下实际进行连接。