Нужен хороший способ использования Delphi для «вращения» (разворота?) Данных в плоской таблице - PullRequest
4 голосов
/ 28 марта 2012

У меня есть таблица данных с записями, которые имеют повторяющееся поле 'position' - представьте себе вращающуюся таблицу с 4 позициями, каждая из которых пронумерована от 1 до 4 inc. Я сохраняю 4 строки таблицы базы данных для каждого поворота, и каждая строка содержит положение поворота от 1 до 4 дюймов, поэтому это поле положения имеет значение 1,2,3,4,1,2,3,4,1,2 и т. Д. быть:

Position  Field1 Field2 Field3
------------------------------
1         4.5    4.6    1.4 
2         5.5    3.6    2.4
3         4.5    7.6    3.4
4         7.5    2.6    4.4
1         2.5    3.6    5.4
2         3.5    9.6    6.4
3         9.5    3.6    7.4
4         1.5    6.6    8.4
1         2.5    9.6    9.4

Я хотел бы отобразить сетку (или сгенерировать таблицу), которая имеет поле положения 1,2,3,4 вдоль вершины (столбцы) и каждое из моих других полей исходных данных (которые были столбцами) теперь как строк. Из приведенного выше примера это будет:

        1        2        3        4
        ------------------------------
Field1  2.5      3.5      9.5      1.5
Field2  9.6      9.6      3.6      6.6
Field3  9.4      6.4      7.4      8.4

Требуется, чтобы отображались только последние 4 записи данных, и я считаю, что это своего рода сводная точка? У меня есть Developer Express 'Quantum Grid, так что я могу легко добавить их сводный набор, если это необходимо. Мое требование состоит в том, что это должно быть очень быстро и отображать только последние 4 позиции, а не суммы или другие агрегаты. Могу ли я быстро написать код? Это то, что инструмент отчетности может сделать? Или я должен использовать решение Pivot Suite?

1 Ответ

2 голосов
/ 28 марта 2012

Вот моя попытка найти решение, которое мне кажется быстрым:

//
//  set alignment to 4 bytes, we will need it that way for later
//
{$A4}
type
  TMyRecord = record
    Position: Integer;
    Field1: Double;
    Field2: Double;
    Field3: Double;
  end;

const
  szMyRecord = SizeOf(TMyRecord);

const
  CMYRECORD_LIST: array[0..8] of TMyRecord = (
    (Position: 1; Field1: 4.5; Field2: 4.6; Field3: 1.4),
    (Position: 2; Field1: 5.5; Field2: 3.6; Field3: 2.4),
    (Position: 3; Field1: 4.5; Field2: 7.6; Field3: 3.4),
    (Position: 4; Field1: 7.5; Field2: 2.6; Field3: 4.4),
    (Position: 1; Field1: 2.5; Field2: 3.6; Field3: 5.4),
    (Position: 2; Field1: 3.5; Field2: 9.6; Field3: 6.4),
    (Position: 3; Field1: 9.5; Field2: 3.6; Field3: 7.4),
    (Position: 4; Field1: 1.5; Field2: 6.6; Field3: 8.4),
    (Position: 1; Field1: 2.5; Field2: 9.6; Field3: 9.4)
  );

const
  CDELTA = 4; // last 4 records
  CCOLUMNS = 4; // columns for target grid

procedure|function...
type
  //
  //  used for accessing our record Fields from 1 to 3 as array
  //
  TMyRecordHack = array[0..2] of Double;

const
  szInteger = SizeOf(Integer);

var
  Index: Integer;
  kIndex: Integer;
  LStartIndex: Integer;
  LRecFields: TMyRecordHack;
  LRecAddr: Integer;
  LMyListAddr: Integer;
  LCol: Integer;
  LRow: Integer;
begin
  LStartIndex := Length(CMYRECORD_LIST) - CDELTA;
  //
  //  store address of first record
  //
  LMyListAddr := Integer(@CMYRECORD_LIST[Low(CMYRECORD_LIST)]);
  //
  //  store the address of TMyRecord at LStartIndex
  //
  LRecAddr :=
    //
    //  CMYRECORD_LIST base address
    //
    LMyListAddr +
    //
    //  record address is RecordIndex * szMyRecord
    //
    LStartIndex * szMyRecord +
    //
    //  skip Position member of TMyRecord
    //
    szInteger;
  for Index := LStartIndex to High(CMYRECORD_LIST) do begin
    //
    //  convert address into pointer and cast pointer as TMyRecordHack
    //
    LRecFields := TMyRecordHack( Ptr( LRecAddr )^ );
    LCol := CMYRECORD_LIST[ Index ].Position;
    for kIndex := Low(LRecFields) to High(LRecFields) do begin
      //
      //  +1 required, we're using a string grid
      //
      LRow := kIndex +1;
      //
      //  display data
      //
      StringGrid1.Cells[ LCol, LRow ] := FloatToStr( LRecFields[ kIndex ] );
    end; // for kIndex := Low(LRecFields) to High(LRecFields) do begin
    //
    //  increment LRecAddr by szMyRecord
    //
    Inc(LRecAddr, szMyRecord);
  end; // for Index := LStartIndex to High(CMYRECORD_LIST) do begin
end;

ОК, TMyRecordHack может быть не лучшим именем, но вы можете называть его как хотите (:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...