Hay que añadir la categoría (TCategoryButtons) y luego los botones a cada categoría (TButtonItem).
Utilizando un código como este, se condigue lo que necesitas. El tuyo puede variar por las tablas o campos, pero será muy parecido.
Código Delphi
[-]
procedure TForm1.Button1Click(Sender: TObject);
Var
LPanel : TCategoryPanel;
Cat : TCategoryButtons;
npaneles : Integer;
i, j : Integer;
but : TButtonItem;
begin
QryCalculos.SQL.Clear;
QryCalculos.SQL.Text := 'select * from (select distinct captionGRUPO from Tabla1) T';
QryCalculos.Open;
npaneles := QryCalculos.RecordCount;
for i := 1 to npaneles do begin
LPanel:=TCategoryPanel.Create(micategorygroup);
LPanel.Caption:= Trim(QryCalculos.FieldByName('captionGRUPO').AsString);
LPanel.PanelGroup:= micategorygroup;
LPanel.TabOrder := i;
LPanel.Name := Trim('Grupo' + i.ToString);
Cat := TCategoryButtons.Create(lPanel);
Cat.Name := 'Category' + i.ToString;
cat.Parent := LPanel;
Cat.Align := alClient;
cat.ButtonWidth := 500;
QryButtons.Close;
QryButtons.SQL.Clear;
QryButtons.SQL.Text := 'select * from tabla1 WHERE captionGrupo=:grupo';
QryButtons.Parameters.ParamByName('grupo').Value := QryCalculos.FieldByName('captionGRUPO').AsString;
QryButtons.Open;
LPanel.Height := 50 * (QryButtons.RecordCount);
for j := 0 to (QryButtons.RecordCount -1) do begin
but := TButtonItem.Create(Cat.Categories.Add.Items);
but.Caption := QryButtons.FieldByName('captionLabel').AsString;
QryButtons.Next;
end;
QryCalculos.Next;
end;
end;
El resultado serán las categorías y los botones.