Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/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
使用Delphi(XE4)和Word_Tlb合并表中的单元格_Delphi_Merge_Ms Word_Cells - Fatal编程技术网

使用Delphi(XE4)和Word_Tlb合并表中的单元格

使用Delphi(XE4)和Word_Tlb合并表中的单元格,delphi,merge,ms-word,cells,Delphi,Merge,Ms Word,Cells,我继承了一个可以工作的应用程序,但我想添加它。我想做的是从第一行合并到第二行的第四或第五个单元格。模板是在word中创建的,通过使用书签,应用程序将这些单词替换为程序中的信息。第二行(技术上是第三行,但我忽略了标题)只使用了6个单元格中的2个,第一个单元格大部分是文本,因此几乎不可读。它会逐行替换书签。表格是模板的一部分,不是通过代码生成的 一个问题是,它使用的是我不习惯的单词_TLB,我已经搜索了几天,寻找一个有效的解决我的问题的方法。我得到的最接近的结果是合并行中的所有单元格 无论如何,我会

我继承了一个可以工作的应用程序,但我想添加它。我想做的是从第一行合并到第二行的第四或第五个单元格。模板是在word中创建的,通过使用书签,应用程序将这些单词替换为程序中的信息。第二行(技术上是第三行,但我忽略了标题)只使用了6个单元格中的2个,第一个单元格大部分是文本,因此几乎不可读。它会逐行替换书签。表格是模板的一部分,不是通过代码生成的

一个问题是,它使用的是我不习惯的单词_TLB,我已经搜索了几天,寻找一个有效的解决我的问题的方法。我得到的最接近的结果是合并行中的所有单元格

无论如何,我会把一些代码片段关于什么我认为是相关的,可以随时更新更多的背景代码,如果需要的话

函数中使用的变量(如果我遗漏了一些明显的内容)

这里是实际行的填充位置。上一节只是添加了数据,但还没有进行任何替换

if qSchedule.FieldByName('IQOQ').AsBoolean then
begin
  MSRow2 := MSTable.Rows.Item(3);
  OleRow := MSRow2;
  OleCell := MSRow2.Cells.Count;
  TRow := MSTable.Rows.Add(OleRow);
  DoRow(FColumns2,TRow);
  TRow.Range.SetRange(0,1); // Range set to get first and second cell to merge
  TRow.Range.Select; //Select the set range
  MSRow2.Application.Selection.Cells.Merge; //How I tried to merge specific cells
  TRow := Nil;
end;
DoRow是用书签替换行的地方。。。如果找到书签,则切换文本

这种方法似乎不起作用。我认为这是因为它是行的范围,但是我不确定如何从一个单元格到另一个单元格,以便我可以合并中间的所有内容

如果我只是执行TRow.Cells.Merge,该方法会合并行中的所有单元格。

也许下面的内容(使用D7和Word2007测试)会有所帮助

它展示了如何完全在代码中创建单词表,然后在 桌子的第二排。出于追踪的目的,它故意有点冗长。 您眼前的问题可能只是需要在要合并的范围的起始单元格上调用Merge(),并且需要将其作为参数传递给要完成合并的单元格

即使下面的代码不能完全解决您的问题,也欢迎您使用下面的代码来说明剩余的问题,而不是您的“实时”代码

顺便说一句,我在下面的代码中使用后期绑定的唯一原因是因为它是从我先前的答案中回收的。作为将来的参考,当您陷入这样的困境时,在使用早期绑定之后,实际上更容易尝试并执行您正在执行的操作(即,使用TLB导入文件中的COM对象,因为在编译过程中,您会发现您是否在正确的对象上调用了正确的方法并提供了正确的参数。缺点是,您必须提供所有参数,而延迟绑定的等价物可能只允许您提供其中的一些参数,例如早期绑定的参数)Open需要12个参数,所有这些参数都需要传递一个OleVariant

另一点是,处理诸如从头开始合并单元格之类的问题的常规方法是记录Word宏并查看其如何操作。通常,这可以轻松地转换为Delphi自动化代码。我记录的宏是一个例外。将其转换为Delphi会导致“不支持接口”异常,因为宏在范围选择上调用了Merge,而COM对象似乎不支持该范围选择

procedure TForm1.CreateTable(Rows, Columns : Integer);
var
  MSWord,
  Document,
  Table,
  Selection,
  Range,
  Cell,
  StartCell,
  EndCell : OleVariant;
  ARow,
  AColumn: Integer;
  RowIndex,
  ColIndex : Integer;
  S : String;
begin
  try
    MsWord := GetActiveOleObject('Word.Application');
  except
    try
      MsWord := CreateOleObject('Word.Application');
      MsWord.Visible := True;
    except
      Exception.Create('Error');
    end;
  end;

  Document := MSWord.Documents.Add;
  MSWord.Selection.Font.Size := 22;
  MSWord.Selection.Font.Bold := true;
  MSWord.Selection.TypeText(#13#10);
  MSWord.Selection.TypeText('This should be center-aligned');
  MSWord.Selection.ParagraphFormat.Alignment := wdAlignParagraphCenter;
  MSWord.Selection.TypeText(#13#10#13#10);
  MSWord.Selection.Font.Size := 12;
  MSWord.Selection.Font.Bold := False;

  Table := MSWord.ActiveDocument.Tables.Add( Range:= MSWord.Selection.Range, NumRows:= Rows, NumColumns:= Columns, DefaultTableBehavior:= wdWord9TableBehavior, AutoFitBehavior:= wdAutoFitFixed);

  try
    for ARow := 1 to Rows do begin
      for AColumn := 1 to Columns do begin
        Cell := Table.Cell(ARow, AColumn);
        RowIndex := Cell.RowIndex;
        ColIndex := Cell.ColumnIndex;
        Caption := IntToStr(RowIndex) + '/' + IntToStr(ColIndex);
        Range := Cell.Range;
        Range.Select;
        if Odd(AColumn) then
          Range.Font.Bold := True
        else
          Range.Font.Bold := False;
        S := Format('Row: %d, col: %d', [RowIndex, ColIndex]);
        MSWord.Selection.Range := Range;
        MSWord.Selection.TypeText(Text := S);
      end;
    end;

    StartCell := Table.Cell(2, 1);  // Put a breakpoint here, switch to Word, then single-step
      // to see what happens
    EndCell := Table.Cell(2, 1 + 3);
    StartCell.Merge(EndCell);
  finally
    Document.Close(SaveChanges := False);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CreateTable(3, 5);
end;
你在一篇评论中问到关于早期和晚期绑定的问题。这个话题太大了一点,没法挤进去 这是答案,但本质上它们是与另一个应用程序(或DLL)中的对象交互的两种不同方式

稍后的绑定是使用变体与它们交互的地方 与这些外部对象交互的大部分细节都是通过 后期绑定。为了以这种方式实现自动化,外部应用程序必须将IDispatch表面化 后期绑定通常从调用CreateOleObject开始,以获取对外部应用程序中顶级自动化对象的引用

后期绑定很容易做到,但同样容易出错,因为接口的细节 外部对象隐藏在与它和Delphi编译器一起使用的变量后面 不能使用其类型安全性来保护您

早期绑定意味着使用对象公开的原始接口 在TLB导入文件中,该文件包含接口方法的对象Pascal定义 和函数,这使编译器能够强制执行代码的类型安全性和语法正确性。因此,这样做(或至少在某些方面)更安全、更容易(正确),而且可以更快一点,因为它减少了使用后期绑定时所涉及的间接层(通过变体)

Eric Harmon关于Delphi中COM编程的书中解释了所有这些以及更多关于Delphi和COM/自动化的内容,摘录如下:


删除了更多的冗余数据。虽然我可以试一试,但我不确定在另一个项目中复制这个问题会有多容易。我不愿意删除所有使用的变量,因为我想这可能会给我实际合并单元格所需的信息。关于合并的评论让我看了一下ICell的closer。哪个反过来,允许我使用您在上面展示的相同技术进行合并。为此,我非常感谢!如果您或其他人不介意回答,请回答以下几个问题?什么是早/晚绑定?这是一个术语,我已经遇到过好几次,但并不真正理解它的含义。使用类似于合并的方法,我会我能说改变文本大小/字体/粗体/斜体…等等?谢谢你的时间和帮助,真的很感谢!我更新了我的答案,解释了更多关于早期v.后期绑定的内容,并在代码中展示了如何实现一些文本效果,如字体大小、粗体和段落对齐。顺便说一句,正如你可能已经收集到的,新用户有点受限
procedure TForm1.CreateTable(Rows, Columns : Integer);
var
  MSWord,
  Document,
  Table,
  Selection,
  Range,
  Cell,
  StartCell,
  EndCell : OleVariant;
  ARow,
  AColumn: Integer;
  RowIndex,
  ColIndex : Integer;
  S : String;
begin
  try
    MsWord := GetActiveOleObject('Word.Application');
  except
    try
      MsWord := CreateOleObject('Word.Application');
      MsWord.Visible := True;
    except
      Exception.Create('Error');
    end;
  end;

  Document := MSWord.Documents.Add;
  MSWord.Selection.Font.Size := 22;
  MSWord.Selection.Font.Bold := true;
  MSWord.Selection.TypeText(#13#10);
  MSWord.Selection.TypeText('This should be center-aligned');
  MSWord.Selection.ParagraphFormat.Alignment := wdAlignParagraphCenter;
  MSWord.Selection.TypeText(#13#10#13#10);
  MSWord.Selection.Font.Size := 12;
  MSWord.Selection.Font.Bold := False;

  Table := MSWord.ActiveDocument.Tables.Add( Range:= MSWord.Selection.Range, NumRows:= Rows, NumColumns:= Columns, DefaultTableBehavior:= wdWord9TableBehavior, AutoFitBehavior:= wdAutoFitFixed);

  try
    for ARow := 1 to Rows do begin
      for AColumn := 1 to Columns do begin
        Cell := Table.Cell(ARow, AColumn);
        RowIndex := Cell.RowIndex;
        ColIndex := Cell.ColumnIndex;
        Caption := IntToStr(RowIndex) + '/' + IntToStr(ColIndex);
        Range := Cell.Range;
        Range.Select;
        if Odd(AColumn) then
          Range.Font.Bold := True
        else
          Range.Font.Bold := False;
        S := Format('Row: %d, col: %d', [RowIndex, ColIndex]);
        MSWord.Selection.Range := Range;
        MSWord.Selection.TypeText(Text := S);
      end;
    end;

    StartCell := Table.Cell(2, 1);  // Put a breakpoint here, switch to Word, then single-step
      // to see what happens
    EndCell := Table.Cell(2, 1 + 3);
    StartCell.Merge(EndCell);
  finally
    Document.Close(SaveChanges := False);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CreateTable(3, 5);
end;