레포트를 엑셀로 내보내기시 칸이 맞지 않아 고민중.. 

아래 코드를 찾아서 엑셀 내보내기일 경우 다시 레포트를 다시 생성해서 내보내도록 수정했다.

 

아래 코드는 문서 내보내기 형식이 xls 파일인 경우, 파일저장 창을 띄우는 예제임

namespace WindowsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }


        private void simpleButton1_Click(object sender, EventArgs e) {
            // Create a report object.
            // Create a report instance, assigned to a Print Tool.
            ReportPrintTool pt = new ReportPrintTool(new XtraReport1());

            // Generate the report's document. This step is required
            // to activate its PrintingSystem and access it later.
            pt.Report.CreateDocument(false);
            // Override the ExportGraphic command.
            pt.PrintingSystem.AddCommandHandler(new ExportToExcelCommandHandler());

            // Show the report's print preview.
            pt.ShowPreviewDialog();

        }
    }

    public class ExportToExcelCommandHandler : ICommandHandler {
        public virtual void HandleCommand(PrintingSystemCommand command, object[] args, IPrintControl control, ref bool handled) {
            if (!CanHandleCommand(command, control))
                return;

            XtraReport1 report = new XtraReport1();
            Stream myStream;
            report.Parameters["IsExporting"].Value = true;
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();

            saveFileDialog1.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.*";
            saveFileDialog1.FilterIndex = 2;
            saveFileDialog1.RestoreDirectory = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
                if ((myStream = saveFileDialog1.OpenFile()) != null) {
                    report.ExportToXls(myStream);

                    myStream.Close();
                }
            } 


            // Set handled to true to avoid the standard exporting procedure to be called.
            handled = true;
        }

        public virtual bool CanHandleCommand(PrintingSystemCommand command, IPrintControl control) {
            // This handler is used for the ExportXls command.
            return command == PrintingSystemCommand.ExportXls;
        }
    }

}

* 원문 : https://www.devexpress.com/Support/Center/Example/Details/E1159

private void MakeTransparent_Example2(PaintEventArgs e)
{

    // Create a Bitmap object from an image file.
    Bitmap myBitmap = new Bitmap("Grapes.gif");

    // Draw myBitmap to the screen.
    e.Graphics.DrawImage(
        myBitmap, 0, 0, myBitmap.Width, myBitmap.Height);

    // Get the color of a background pixel.
    Color backColor = myBitmap.GetPixel(1, 1);

    // Make backColor transparent for myBitmap.
    myBitmap.MakeTransparent(backColor);

    // Draw the transparent bitmap to the screen.
    e.Graphics.DrawImage(
        myBitmap, myBitmap.Width, 0, myBitmap.Width, myBitmap.Height);
}

참고 : https://msdn.microsoft.com/en-us/library/8517ckds(v=vs.110).aspx

TestClass 의 MyMethod를 실행하는 예제

파라미터 유무에 따라 실행함

	static void Main(string[] args)
        {
            var testClass = new TestClass();
            Type myType = testClass.GetType();
            MethodInfo[] myArrayMethodInfo = myType.GetMethods();
            var methods = myArrayMethodInfo.Where(x => x.Name == "MyMethod");

            foreach(var method in methods)
            {
                ParameterInfo[] parameters = method.GetParameters();

                if (parameters.Length == 0)
                {
                    method.Invoke(testClass, null);
                }
                else
                {
                    method.Invoke(testClass, new object[] { "TEST" });
                }
            }
        }

TestClass 

    class TestClass
    {
        public void MyMethod()
        {
            Console.WriteLine("MyMethod()");
        }

        public void MyMethod(string name)
        {
            Console.WriteLine("MyMethod() - Name = {0}", name);
        }
    }

 

HttpWebRequest 로 웹 페이지 호출시

요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다. 

이런 오류가 발생하였다.

 

찾아보니 해당사이트에서 지원하는 ssl/tls 버젼이 상위버전이라 그런 듯...

 

해결방법은 아래 코드를 추가해준다.

 

        ServicePointManager.Expect100Continue = true;
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
                            | SecurityProtocolType.Tls11
                            | SecurityProtocolType.Tls12
                            | SecurityProtocolType.Ssl3;

* 참고 : https://stackoverrun.com/ko/q/11480393

 

c# - 요청이 중단되었습니다. SSL/TLS 보안 채널을 만들지 못했습니다. | System.Net.WebException

내 webApi는 타사 웹 API 서비스를 사용하고 있습니다. 문제는 내 로컬 컴퓨터와 Azure 웹 서비스에서 완벽하게 작동한다는 것입니다. 하지만이 솔루션을 Azure VM 인스턴스로 전송하면이 오류가 발생�

stackoverrun.com

 

<추가>

MS Azure로 파일 업로드시 

"The server encountered an unknown failure: 기본 연결이 닫혔습니다. SSL/TLS 보안 채널에 대한 트러스트 관계를 설정할 수 없습니다."

이런 오류가 발생하는 경우에도 아래 코드로 해결된다.

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

 

*참고 : https://www.it-swarm.dev/ko/c%23/ssltls-%EB%B3%B4%EC%95%88-%EC%B1%84%EB%84%90%EC%97%90-%EB%8C%80%ED%95%9C-%ED%8A%B8%EB%9F%AC%EC%8A%A4%ED%8A%B8-%EA%B4%80%EA%B3%84%EB%A5%BC-%EC%84%A4%EC%A0%95%ED%95%A0-%EC%88%98-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-soap/957861508/

데이터가 제법 많은 목록에서 제목을 LIKE 검색하는 경우,

혹은 공백을 포함한 문자열의 공백 제거 후 검색을 하는 경우,

속도 이슈가 발생한다. 


이런 경우 DBMS에서 제공하는 FullTextSearch 기능을 사용하면 훨씬 빠른 결과를 얻을 수 있다. 


그런데 Devexpress GridControl을 사용하는 경우.... 

AutoFilter에서 검색시 Filter 정보에는 

contains([검색필드명], N'검색어') 로 입력되며,


실제로 DBMS에서 실행되는 Query문을 확인해보면 

    (isnull(CharIndex(N'검색어', [검색필드명]), 0) > 0 


이런 식이다... 대략 낭패 OTL


어찌해야 AutoFilter에서  FullTextSearch를 사용할 수 있을까?


찾아보니 아래와 같이 ICustomFunctionOperatorFormattable 인터페이스를 구현한 클래스를 추가하면 가능하다는 것을 알았다.


< 구현 방법 >


1. ICustomFunctionOperatorFormattable 를 구현한 클래스를 생성한다.

이름 지정과 포멧 함수 구현이 핵심인 듯...

using System.Data;
using DevExpress.Xpo.DB;
using DevExpress.Data.Filtering;

public class FullTextContainsFunction : ICustomFunctionOperatorFormattable {
    #region ICustomFunctionOperator Members
    // Evaluates the function on the client 
    public object Evaluate(params object[] operands) {
        // Full text search is not available on the client and should not be used there 
        throw new NotImplementedException();
    }
    public string Name {
        get { return "FullTextContains"; }
    }
    public Type ResultType(params Type[] operands) {
        return typeof(bool);
    }
    #endregion
    #region ICustomFunctionOperatorFormattable Members
    // The function's expression to be evaluated on the server 
    public string Format(Type providerType, params string[] operands) {
        // This example implements the function for MS SQL databases only 
        if (providerType == typeof(MSSqlConnectionProvider))
            return string.Format("contains({0}, {1})", operands[0], operands[1]);
        throw new NotSupportedException(string.Concat("This provider is not supported: ", 
            providerType.Name));
    }
    #endregion
}


2. 프로그램 시작시 ICustomFunctionOperatorFormattable 를 구현한 클래스의 인스턴스를 CriteriaOperator에 커스텀 함수로 등록한다.


// program.cs 나 MainForm 에 추가한다.

CriteriaOperator.RegisterCustomFunction(new FullTextContainsFunction());



3. 그리고 필터에서 검색시 아래와 같이 필터를 입력한다.


CriteriaOperator.Parse("FullTextContains([필드명], '검색어')");




결과는 아주 잘 작동한다.


* 참고 : https://documentation.devexpress.com/CoreLibraries/3246/DevExpress-ORM-Tool/Examples/How-to-Implement-a-Full-Text-Search







컬럼을 각 컬럼의 길이로 맞추는 경우.. 
보통 PadRight() 나 string.format("{0, -길이 }") 사용하는데..

문제는 이 공백 문자 넓이가 다른 경우 원하던 결과를 얻을 수 없다.



원인은.. 폰트 때문이란걸 알았음.. 

Default 폰트를 "굴림"으로 사용중인데.. 

이걸 "굴림체"로 바꾸니 해결됨.




글꼴은 대부분 같은 이름으로 두개씩 존재합니다.

굴림 / 굴림체 , 돋움 / 돋움체 등이지요.

 

두 글꼴은 글꼴 방식에 있어서 차이가 존재합니다.

(제가 글꼴을 전문적으로 다루는게 아니라서 설명하기 힘들지만 찾아보면 나올겁니다.)

 

굴림 : 영문소문자/대문자/숫자/공백/한글 등의 각 한 문자의 크기가 다 다릅니다.

굴림체 : 영문소문자/대문자/숫자/공백/한글 등의 각 한문자의 크기가 고정되어 있습니다.

 

~체 글꼴로 표시하면 위의 예시는 원하는 레이아웃으로 표시될거고

~ 글꼴로 보면 정렬이 제대로 맞지 않는 것으로 표시될겁니다. 


* 발췌 : http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=17&MaeulNo=8&no=71840&ref=71840


* 참고 : 굴림과 굴림체의 차이 http://tip.daum.net/question/70757137

 

엑셀 내보내기시 이런 식으로 (모든 컬럼이 최소사이즈로) 출력된다면..

 

 

당황하지 말고

BestFitColumns 메소드를 이용하면 해결됨..

 

단.. BestFitColumns 전에 AutoWith 값을 false로 해줘야함.

 

advBandedGridView.OptionsPrint.AutoWidth = false;
advBandedGridView.OptionsView.ColumnAutoWidth = false;
advBandedGridView.BestFitColumns();

이건 삽질 1시간 짜리임.

 

* 참고 :  https://www.devexpress.com/Support/Center/Question/Details/Q253087

 

 

Tip.하나 더~

 

Band Header width 에 Column Width를 맞추고 싶다면

 

private void BestFitBands(AdvBandedGridView view)
{
            view.BeginUpdate();
            view.OptionsView.ShowColumnHeaders = true;
            foreach (BandedGridColumn col in view.Columns)
                col.Caption = col.OwnerBand.Caption;
            view.BestFitColumns();
            view.OptionsView.ShowColumnHeaders = false;
            view.EndUpdate();
}

 

요기서 발췌함. ( https://www.devexpress.com/Support/Center/Question/Details/Q304079 )

 

 

엑셀 출력시.. 가장쉬운 방법이

Grid에 Data Binding 한 후 그대로 Export 하는 방법인데..


//

gridControl.ExportToXlsx(path);


했더니 .. 그리드 헤더 부분이 아래처럼 Grouping 되서 출력된다...


문제는 ExportType!


// Export 시, 아래처럼 옵션을 설정할 수 있다

XlsxExportOptionsEx xlsxOptions = new XlsxExportOptionsEx();
xlsxOptions.ShowGridLines = true;   // 라인출력 
xlsxOptions.SheetName = "test";    // sheet 명
xlsxOptions.ExportType = DevExpress.Export.ExportType.WYSIWYG;    // ExportType

gridControl.ExportToXlsx(exportFilePath, xlsxOptions);


WYSIWYG (위지윅)이란? what you see is what you get  (보이는 데로 얻는다. )

보이는 그데로 출력된다는 IT 용어.


 



이제야 내가 의도한데로 나옴.. 삽질 3시간함.


자세한 설명은 아래 링크 참조 ..

https://documentation.devexpress.com/#WindowsForms/CustomDocument17733



하나 더..

그리드에서 Export 할때 유용한 Method ..


http://stackoverflow.com/questions/14583067/devexpress-export-gridview-to-excel


// 위 Link에서 내용 발췌

private void mnuExportTable_ItemClick_1(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
    using (SaveFileDialog saveDialog = new SaveFileDialog())
    {
        saveDialog.Filter = "Excel (2003)(.xls)|*.xls|Excel (2010) (.xlsx)|*.xlsx |RichText File (.rtf)|*.rtf |Pdf File (.pdf)|*.pdf |Html File (.html)|*.html";
        if (saveDialog.ShowDialog() != DialogResult.Cancel)
        {
            string exportFilePath = saveDialog.FileName;
            string fileExtenstion = new FileInfo(exportFilePath).Extension;

            switch (fileExtenstion)
            {
                case ".xls":
                    gridControl.ExportToXls(exportFilePath);
                    break;
                case ".xlsx":
                    gridControl.ExportToXlsx(exportFilePath);
                    break;
                case ".rtf":
                    gridControl.ExportToRtf(exportFilePath);
                    break;
                case ".pdf":
                    gridControl.ExportToPdf(exportFilePath);
                    break;
                case ".html":
                    gridControl.ExportToHtml(exportFilePath);
                    break;
                case ".mht":
                    gridControl.ExportToMht(exportFilePath);
                    break;
                default:
                    break;
            }

            if (File.Exists(exportFilePath))
            {
               try
               {
                   //Try to open the file and let windows decide how to open it.
                   System.Diagnostics.Process.Start(exportFilePath);
                }
                catch
                {
                    String msg = "The file could not be opened." + Environment.NewLine + Environment.NewLine + "Path: " + exportFilePath;
                    MessageBox.Show(msg, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
             }
             else
             {
                 String msg = "The file could not be saved." + Environment.NewLine + Environment.NewLine + "Path: " + exportFilePath;
                 MessageBox.Show(msg, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
             }
        }
    }
}



https://www.devexpress.com/Support/Center/Question/Details/T109932



다중선택 모드인 경우

몇 Row 선택후 Filtering 하게 되면 이전 선택정보를 잃어버리는데..

아래 처럼 하면 선택된 Row를 저장하게됨.

위 링크 참조 소스는 링크에서 맨 밑 첨부파일에서 발췌함.



void SubscribeEvents()

{    

          gridView1.MouseDown += new MouseEventHandler(gridView1_MouseDown);
            gridView1.MouseUp += new MouseEventHandler(gridView1_MouseUp);
            gridView1.ColumnFilterChanged += gridView1_ColumnFilterChanged;
        }

        void gridView1_ColumnFilterChanged(object sender, EventArgs e)
        {
            RestoreSelection(sender as GridView);
        }

        void RestoreSelection(GridView view)
        {
            BeginInvoke(new Action(() =>
            {
                for (int i = 0; i < selectedRows.Count; i++)
                    view.SelectRow(view.GetRowHandle(selectedRows[i]));
            }));
        }

        List<int> selectedRows = new List<int>();
        void gridView1_MouseUp(object sender, MouseEventArgs e)
        {
            GridView view = sender as GridView;
            RestoreSelection(view);
        }

        void gridView1_MouseDown(object sender, MouseEventArgs e)
        {
            GridView view = sender as GridView;
            GridHitInfo hi = view.CalcHitInfo(e.Location);
            if (hi.Column.FieldName == "DX$CheckboxSelectorColumn")
            {
                if (!hi.InRow)
                {
                    bool allSelected = view.DataController.Selection.Count == view.DataRowCount;
                    if (!allSelected)
                    {
                        for (int i = 0; i < view.RowCount; i++)
                        {
                            int sourceHandle = view.GetDataSourceRowIndex(i);
                            if (!selectedRows.Contains(sourceHandle))
                                selectedRows.Add(sourceHandle);
                        }
                    }
                    else selectedRows.Clear();
                }
                else
                {
                    int sourceHandle = view.GetDataSourceRowIndex(hi.RowHandle);
                    if (!selectedRows.Contains(sourceHandle))
                        selectedRows.Add(sourceHandle);
                    else
                        selectedRows.Remove(sourceHandle);
                }
            }
            RestoreSelection(view);
        }


MemoEdit 에 라인수를 제한하고 싶은경우


void memoEdit_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
            string s = e.NewValue as string;
            int index = 0;
            int lineCount = 0;
            int startIndex = 0;


            while ((index = s.IndexOf( "\r\n" , startIndex)) >= 0)
            {
                startIndex = index + 2;
                lineCount++;
            }


            if (lineCount > 9)
            {
                XtraMessageBox.Show(this, "최대 10줄까지 입력가능합니다.", "입력제한알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                e.Cancel = true;
            }

        }



참고

http://www.devexpress.com/Support/Center/Question/Details/Q51262


한라인의 문자수를 제한하고 싶은경우 참고

http://www.devexpress.com/Support/Center/Question/Details/Q21297 

+ Recent posts