programing

SSRS 디자인 모드에서 테이블 릭스 열을 쉽게 재 배열 할 수있는 방법이 있습니까?

nasanasas 2020. 11. 30. 17:53
반응형

SSRS 디자인 모드에서 테이블 릭스 열을 쉽게 재 배열 할 수있는 방법이 있습니까?


테이블 릭스에 20 개 이상의 열이 포함 된 SSRS 보고서가 있습니다. 사용자는 데이터가 정상이라고 결정했지만 열을 이동하기를 원합니다 ( 한숨! ).

열을 다시 정렬하는 것이 쉬운 것 같습니다 (열 3을 열 1로 이동, 열 4 및 5 교체 등). 그러나 끌어서 놓기가 작동하지 않는 것 같고 유일한 해결책은 원래 열을 삭제하고 올바른 위치에 다시 삽입하는 것입니다 (그리고 열에 대해 이미 생성 된 표현식 및 서식을 다시 적용).

이 작업을 수행하는 더 쉬운 방법이 있습니까? 프로그래밍 방식 솔루션을 원하지는 않지만 디자인 모드에서 한 번만 변경하면됩니다.


디자이너를 통해 열을 이동하는 방법이 있습니다.

  1. 이동하려는 빈 열의 수를 목적지 지점에 삽입하십시오.
  2. 이동하려는 셀 (헤더 열 아님)을 Shift- 왼쪽 클릭
  3. 마우스 오른쪽 버튼을 클릭하고 잘라 내기 명령을 선택합니다.
  4. 대상 열 상단을 마우스 오른쪽 버튼으로 클릭하고 붙여 넣기를 선택합니다.
  5. 이제 비어있는 이전 열 삭제

XML을 읽을 수 있다면 (태그의 시작과 끝 등을 이해하기 만하면됩니다) 작업을 쉽게 수행 할 수 있습니다. 다음과 같은 일련의 단계를 수행 할 수 있습니다.

  1. 먼저 원본 보고서를 다른 파일에 복사하여 백업하십시오.
  2. 솔루션 탐색기에서 보고서를 마우스 오른쪽 단추로 클릭하고 "코드보기"를 선택합니다.
  3. 이것은 보고서의 RDL을 엽니 다 --- 단순한 xml 파일 일뿐입니다.
  4. 이제 RDL 파일에서 "Tablix1"태그를 찾습니다. <Tablix Name="Tablix1"> ....</Tablix >
  5. 이제 <Textbox Name="...">...</Texbox>태그 내에 중첩 된 다른 " "태그 를 찾아야 <TablixCells><TablixCell><CellContents>....합니다.
  6. 이제 단순히 순서를 재정렬하여 보고서의 열을 쉽게 재정렬 할 수 <Textbox...>...</Texbox>있으며 새 열 순서가 지정된 새 보고서를 갖게됩니다.

사실, 당신은 전체 (잘라 내기 및 붙여 넣기)로 이동해야 <TablixCell>합니다 (사이에있는 모든 열의 요소 <TablixCell></TablixCell>포함 <TablixCell></TablixCell>태그 자체).

예를 들어 아래 예의 열을 재 배열하여 "제품 ID"열이 "제품 이름"열 앞에 오도록 하려면 "제품 이름"셀 요소 주변의 전체 섹션을 선택하고 잘라냅니다 (처음 <TablixCell>부터 제 </TablixCell>)하고 붙여 </TablixCell> 은 "제품 ID"열의. 테이블 릭스에 정의 된 각 행에 대한
전체 <TablixCell>요소 집합이 있습니다. 각각은 별도의 <TablixRow>요소에 있습니다. 기본 헤더 열 (열 이름이 설정된 위치)을 그대로 둔 경우 첫 번째<TablixRow>해당 헤더 행을 정의하고 두 번째 행은 열의 데이터를 정의하며 편집하려는 행입니다. 데이터 열을 다시 정렬 한 후에는 헤더 열 (있는 경우)에 대해 동일한 작업을 수행하거나 디자이너를 사용하여 열의 이름을 변경하여 지금 열에있는 데이터와 일치시켜야합니다.

그러나 이것은 너무 복잡해서 디자이너를 사용하여 열을 이동할 새 열을 삽입하고 해당 열에 대한 적절한 데이터 소스로 설정 한 다음 원래 열을 삭제하는 것만으로 열을 이동하는 것이 더 쉬울 것입니다. . 아래 예에서는 Product ID 뒤에 새 열을 삽입 하고 ProductName 데이터 소스 열 (헤더 행에 "Product Name"로 설정 됨)으로 설정 한 다음 왼쪽 의 원래 Product Name을 삭제합니다 .

...
<TablixCell>
  <CellContents>
    <Textbox Name="ProductName">
      <CanGrow>true</CanGrow>
      <KeepTogether>true</KeepTogether>
      <Paragraphs>
        <Paragraph>
          <TextRuns>
            <TextRun>
              <Value>=Fields!ProductName.Value</Value>
              <Style />
            </TextRun>
          </TextRuns>
          <Style />
        </Paragraph>
      </Paragraphs>
      <rd:DefaultName>ProductName</rd:DefaultName>
      <Style>
        <Border>
          <Color>LightGrey</Color>
          <Style>Solid</Style>
        </Border>
        <PaddingLeft>2pt</PaddingLeft>
        <PaddingRight>2pt</PaddingRight>
        <PaddingTop>2pt</PaddingTop>
        <PaddingBottom>2pt</PaddingBottom>
      </Style>
    </Textbox>
  </CellContents>
</TablixCell>
<TablixCell>
  <CellContents>
    <Textbox Name="ProductID">
      <CanGrow>true</CanGrow>
      <KeepTogether>true</KeepTogether>
      <Paragraphs>
        <Paragraph>
          <TextRuns>
            <TextRun>
              <Value>=Fields!ProductID.Value</Value>
              <Style />
            </TextRun>
          </TextRuns>
          <Style />
        </Paragraph>
      </Paragraphs>
      <rd:DefaultName>ProductID</rd:DefaultName>
      <Style>
        <Border>
          <Color>LightGrey</Color>
          <Style>Solid</Style>
        </Border>
        <PaddingLeft>2pt</PaddingLeft>
        <PaddingRight>2pt</PaddingRight>
        <PaddingTop>2pt</PaddingTop>
        <PaddingBottom>2pt</PaddingBottom>
      </Style>
    </Textbox>
  </CellContents>
</TablixCell>
...

잘라 내기 / 붙여 넣기 후 다음과 같이됩니다.

...
<TablixCell>
  <CellContents>
    <Textbox Name="ProductID">
      <CanGrow>true</CanGrow>
      <KeepTogether>true</KeepTogether>
      <Paragraphs>
        <Paragraph>
          <TextRuns>
            <TextRun>
              <Value>=Fields!ProductID.Value</Value>
              <Style />
            </TextRun>
          </TextRuns>
          <Style />
        </Paragraph>
      </Paragraphs>
      <rd:DefaultName>ProductID</rd:DefaultName>
      <Style>
        <Border>
          <Color>LightGrey</Color>
          <Style>Solid</Style>
        </Border>
        <PaddingLeft>2pt</PaddingLeft>
        <PaddingRight>2pt</PaddingRight>
        <PaddingTop>2pt</PaddingTop>
        <PaddingBottom>2pt</PaddingBottom>
      </Style>
    </Textbox>
  </CellContents>
</TablixCell>
<TablixCell>
  <CellContents>
    <Textbox Name="ProductName">
      <CanGrow>true</CanGrow>
      <KeepTogether>true</KeepTogether>
      <Paragraphs>
        <Paragraph>
          <TextRuns>
            <TextRun>
              <Value>=Fields!ProductName.Value</Value>
              <Style />
            </TextRun>
          </TextRuns>
          <Style />
        </Paragraph>
      </Paragraphs>
      <rd:DefaultName>ProductName</rd:DefaultName>
      <Style>
        <Border>
          <Color>LightGrey</Color>
          <Style>Solid</Style>
        </Border>
        <PaddingLeft>2pt</PaddingLeft>
        <PaddingRight>2pt</PaddingRight>
        <PaddingTop>2pt</PaddingTop>
        <PaddingBottom>2pt</PaddingBottom>
      </Style>
    </Textbox>
  </CellContents>
</TablixCell>
...

RDL 작업에 대한 또 다른 참고 사항 :
오류가 발생하면 보고서에 오류 메시지가 표시되고 데이터가 표시되지 않습니다.

RDL (Report Definition Language, XML 유형)에 익숙하지 않은 경우 이러한 유형의 오류는 보고서를 사용할 수 없게 만드는 경우를 처리하기가 매우 어려울 수 있습니다.

위에서 언급 한 디자이너에서 새 열 추가 및 이전 항목 삭제 방법을 사용하는 것이 훨씬 안전합니다. 이렇게하면 RDL에서 벗어날 수 있으므로 보고서가 손상 될 가능성이 줄어 듭니다.


테이블 릭스의 열 머리글을 끌어서 열 순서를 변경하려고 할 때이 상황이 발생했습니다. 작동하지 않습니다! 그러나 셀을 드래그하여 다른 셀에 (조심스럽게) 드롭 한 다음 셀을 교체 할 수 있음을 발견했습니다. 이렇게하면 새로운 빈 열을 만들지 않고도 머리글과 콘텐츠 셀을 교체하여 열을 다시 정렬 할 수 있습니다. 보고서 본문 너비를 늘리지 않고 PDF 렌더링에서 빈 페이지를 생성하지 않으려는 경우 더 좋습니다. 물론 수정할 수 있습니다. 다시. 셀을 드래그하려면 셀을 한 번 클릭하되 편집 모드로 들어 가지 않은 다음 테두리 주위로 마우스를 가져간 다음 '이동'커서가 나타나면 드래그합니다. 이는 Visual Studio 2017에서 사용할 수있는 보고서 디자이너에 적용됩니다.


내 솔루션 :

using System;
using System.IO;
using System.Linq;
using System.Xml;

namespace MoveSsrsColumns
{
    class TablixColumnReorderer
    {
        readonly XmlDocument _xData = new XmlDocument();
        readonly XmlNamespaceManager _nsManager;
        readonly XmlElement _tablixNode;

        public TablixColumnReorderer(string rdlFileName, string tablixName)
        {
            using (var fs = new FileStream(rdlFileName, FileMode.Open))
            using (var xr = XmlReader.Create(fs))
                _xData.Load(xr);
            _nsManager = new XmlNamespaceManager(_xData.NameTable);
            _nsManager.AddNamespace("def", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition");
            _tablixNode =
                _xData.SelectNodes(string.Format(TablixXPath, tablixName)_nsManager)
                ?.Cast<XmlElement>().FirstOrDefault()
                ?? throw new ApplicationException("Tablix node notfound");
        }

        const string TablixXPath = @"
            /def:Report
                /def:ReportSections
                    /def:ReportSection
                        /def:Body
                            /def:ReportItems
                                /def:Tablix[@Name='{0}']";

        const string SearchColumnXPath = @"
            def:TablixBody
                /def:TablixRows
                    /def:TablixRow
                        /def:TablixCells
                            /def:TablixCell
                                /def:CellContents
                                    /def:*[@Name='{0}']";

        const string ParentTablixCellXPath = "parent::def:CellContents/parent::def:TablixCell";

        int FindColumn(string columnControlName)
        {
            var columnControl = _tablixNode
                .SelectNodes(string.Format(SearchColumnXPath, columnControlName), _nsManager)
                ?.Cast<XmlElement>()
                .Single();
            if (columnControl==null)
                throw new ArgumentException($"Column with control {columnControlName} notfound");
            if (!(columnControl.SelectSingleNode(ParentTablixCellXPath, _nsManager) is XmlElement tablixCell))
                throw new ArgumentException($"Tablix cell for column with control {columnControlName} notfound");
            var columnIndex = ((XmlElement) tablixCell.ParentNode)
                ?.ChildNodes
                .Cast<XmlElement>()
                .TakeWhile(e=>e!=tablixCell)
                .Count() ?? -1;
            if (columnIndex==-1)
                throw new ArgumentException($"Cannot get index for column with control {columnControlName}");
            return columnIndex;
        }

        public void SetPosition(string sourceColumnControlName, string destinationColumnControlName)
        {
            SetPosition(FindColumn(sourceColumnControlName), FindColumn(destinationColumnControlName));
        }

        public void SetPosition(string sourceColumnControlName, int destinationColumnIndex)
        {
            SetPosition(FindColumn(sourceColumnControlName), destinationColumnIndex);
        }

        public void SetPosition(int sourceColumnIndex, string destinationColumnControlName)
        {
            SetPosition(sourceColumnIndex, FindColumn(destinationColumnControlName));
        }

        const string TablixCellsXPath = "def:TablixBody/def:TablixColumns";
        const string TablixRowCellsXPath = "def:TablixBody/def:TablixRows/def:TablixRow/def:TablixCells";
        public void SetPosition(int sourceColumnIndex, int destinationColumnIndex)
        {
            var tablixColumnsNode = _tablixNode
                .SelectSingleNode(TablixCellsXPath, _nsManager) as XmlElement
                ?? throw new ApplicationException("TablixColumns node notfound");
            tablixColumnsNode.InsertBefore(
                tablixColumnsNode.ChildNodes[sourceColumnIndex],
                tablixColumnsNode.ChildNodes[destinationColumnIndex]
            );
            var tablixRowsCells = _tablixNode
                .SelectNodes(TablixRowCellsXPath, _nsManager)
                ?.Cast<XmlElement>()
                ?? throw new ApplicationException("Tablix rows cells notfound");
            foreach (var cells in tablixRowsCells)
                cells.InsertBefore(
                    cells.ChildNodes[sourceColumnIndex],
                    cells.ChildNodes[destinationColumnIndex]
                );
        }

        public void Save(string rdlFileName)
        {
            using (var fs = new FileStream(rdlFileName, FileMode.Create))
            using (var xw = XmlWriter.Create(fs, new XmlWriterSettings
            {
                Indent = true,
                IndentChars = "  "
            }))
                _xData.Save(xw);
        }
    }
}

용법:

public static void Main(string[] args)
{
    var tcr = new TablixColumnReorderer("myreport.rdl", "Tablix1");
    tcr.SetPosition("bill_number", 0);
    tcr.SetPosition("account", 1);
    tcr.SetPosition("to_date", 2);
    tcr.Save("myreport#2.rdl");
    Console.WriteLine("done");
    Console.ReadKey(true);
}

참고URL : https://stackoverflow.com/questions/12642844/is-there-an-easy-way-to-rearrange-tablix-columns-in-ssrs-design-mode

반응형