ReoGrid Forum

Fast and powerful .NET Spreadsheet Component

You are not logged in.

Announcement

This forum has been archived and no longer accepts new user registrations. Please report your questions, problems, and feedback to the issue page of ReoGrid on GitHub. Thank you for your cooperation.

https://github.com/unvell/ReoGrid/issues

#1 2016-12-13 03:25:47

sirmfletcher
Member
Registered: 2016-12-10
Posts: 8

Class for Adding Partial Support on Copy to Clipboard in HTMLFormat

I've created a couple of classes to support copying a range of cells in reogrid and copying to the clipboard as html.
Currently supported features are:

Cell text color, background color, font name, size, bold, text align both horizontal and vertical.
The class can be instantiated and then called using

 public void PasteHTMLFormatToClipboard(ReoGridControl rgc)

// the method will clear the clipboard and past the htmlclipboard fragment

 // example from demo project in button handler for convert button
 private void btnConvert_Click(object sender, EventArgs e)
        {
            HTMLClipboardFormatGenerator htmlGen = new HTMLClipboardFormatGenerator();
            
            htmlGen.PasteHTMLFormatToClipboard(rgc);//rgc == name of the reoGrid Control with a selection of cell(s) selected/highlighted

        } // end of btnConvert_Click()

Screenshots
From here
reogridspreadsheetselected.png?ssl=1&w=450
to here
htmlpastetoword.png?ssl=1&w=450

Below is a copy of the sourcecode file

/*****************************************************************************
 * 
 * HTMLCLipboardFormatGenerator
 * Author: Matthew Fletcher <sirmfletcher@gmail.com>
 *
 * For use with ReoGrid - .NET Spreadsheet Control 
 * Author: Jing <lujing at unvell.com>
 * http://reogrid.net/
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
 * PURPOSE.
 *
 * 
 *
 * The MIT License (MIT)
 * Copyright (c) 2016 by M.Fletcher
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the 
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 * 
 ****************************************************************************/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using unvell.ReoGrid;
using System.Xml.Linq;
using System.Windows.Forms;
//using JR.Utils.GUI.Forms; for FlexibleMessageBox.cs class which supports scrollbars in a messagbox dlg class
/// <summary>

/// Not Supported or Implemented:  FillStyles, Patterns, Cell Borders, its hardcoded on line#575 to put a border around all cells
/// </summary>
namespace ReoGridBetterTextTest
{
    /// <summary>
    /// Purpose: Convert a selected range of cells into htmlclipboard format
    /// can then be pasted into other apps that recognize that format like MS Word etc..
    /// </summary>
    public class HTMLClipboardFormatGenerator
    {
        protected int _totalRows;
        protected int _totalCols;

        protected ReoGridControl _rgc = null;
        protected Worksheet _currWorksheet = null;
        protected RangePosition _selRange;

        protected string strHTMLClipboardFormat = "";
        protected string strPreviewText = "";
        protected StringBuilder _sbClipboardFormat = null;
        protected StringBuilder _sbHTML = null;
        protected StringBuilder _sbPreHeader = null;
        protected StringBuilder _sbStringStylesCombined = null;
      
        #region XElements to generate HTML Doc Fragment

        protected XElement _html = new XElement("html");
        protected XElement _head = new XElement("head");
        protected XElement _style = new XElement("style");
        protected XElement _body = new XElement("body");
        protected XElement _table = new XElement("table");

        // contains each of the rows of the table, so we can modify by row for styles etc..
        // much easier than traversing the tree!
        protected List<XElement> _listRows = new List<XElement>();

       
        // this is used for comparison to see if a style already exists if so, don't add it, just reference it
        // used to prevent creation of exact duplicate styles!
        // this just contains the attributes set as a string for a given style, containing a list of these styles
        protected List<HTMLStyle> _listHTMLStyles = new List<HTMLStyle>();

        protected int styleNum = 1;

        #endregion XElements to generate HTML Doc Fragment

        protected string[] _enumNames;

        protected Dictionary<string, Func<WorksheetRangeStyle, string>> dictFlagToFunction = new Dictionary<string, Func<WorksheetRangeStyle, string>>();




        #region Prefix Header 
        protected const string pHeaderPart1 = "Version:0.9";
        protected const string pHeaderPart2 = "\r\nStartHTML:";
        protected const string pHeaderPart3 = "\r\nEndHTML:";
        protected const string pHeaderPart4 = "\r\nStartFragment:";
        protected const string pHeaderPart5 = "\r\nEndFragment:";

        protected const string strPreFragStart = "\r\n<!--StartFragment-->";
        protected const string strPostFragStop = "<!--EndFragment-->\r\n";
  
        
        protected const string strPostHTMLHeader = "\r\n</body>\r\n</html>";

        
        // used to calculate the length of the preHeader 
        // it must be calculated beforehand for use in calculating other values
        protected int nPreHeaderLength = pHeaderPart1.Length
                                    + pHeaderPart2.Length + 10  // each positional char field is fixed length of 10 chars value 
                                    + pHeaderPart3.Length + 10 // each positional char field is fixed length of 10 chars value
                                    + pHeaderPart4.Length + 10 // each positional char field is fixed length of 10 chars value
                                    + pHeaderPart5.Length + 10;// each positional char field is fixed length of 10 chars value


        // the 4 variables that hold the char pos to build the header before the html document!
        // each string must be total length of 10chars after convertering the int value to string
        // So we Padd left with 0's <zeros>
        protected string strStartHTMLPos;
        protected string strEndHTMLPos;
        protected string strStartFragPos;
        protected string strEndFragPos;

        #endregion Prefix Header
        

        public HTMLClipboardFormatGenerator()
        {
            InitializeDictionary();

        } // end of HTMLClipboardFormatGenerator()


        protected virtual void GetCurrentWorksheetSelectedRange()
        {
            _currWorksheet = _rgc.CurrentWorksheet;
            _selRange = _currWorksheet.SelectionRange;

            // now we know how many cells in both directions we are working with
            _totalCols = _selRange.Cols;
            _totalRows = _selRange.Rows;

            // size the stringbuilder to a guessestimate lol
            // each column causes a <td></td>  each row causes a <tr></tr>
            // doesn't take into account styles or cell merges! just a rough starting guess
            // so that sb doesn't do a bunch of resizes right near the beginnning.
            if (_sbHTML == null)
                _sbHTML = new StringBuilder((_totalCols * 9 * _totalRows + _totalRows * 9 + 300));
            else
                _sbHTML.Clear();

        } // end of GetCurrentWorksheetSelectedRange()

        /// <summary>
        /// Created so we can use a for loop to get enum flags and call function for flag set by mapping flag name to function
        /// eliminates a huge switch statement or having to just call all functions and check if flag set before getting value
        /// </summary>
        protected void InitializeDictionary()
        {
           

            _enumNames = Enum.GetNames(typeof(PlainStyleFlag));

            dictFlagToFunction.Add("None", GetUnUsedUnionStyle);
            dictFlagToFunction.Add("FontName", GetFontNameStyle);
            dictFlagToFunction.Add("FontSize", GetFontSizeStyle);
            dictFlagToFunction.Add("FontStyleBold", GetFontBoldStyle);
            dictFlagToFunction.Add("FontStyleItalic", GetFontItalicStyle);
            dictFlagToFunction.Add("FontStyleStrikethrough", GetFontStrikethroughStyle);
            dictFlagToFunction.Add("FontStyleUnderline", GetFontUnderlineStyle);
            dictFlagToFunction.Add("TextColor", GetTextColorStyle);
            dictFlagToFunction.Add("BackColor", GetBackColorStyle);
            dictFlagToFunction.Add("LineColor", GetLineColorStyle);
            dictFlagToFunction.Add("LineStyle", GetLineStyle);
            dictFlagToFunction.Add("LineWeight", GetLineWeightStyle);
            dictFlagToFunction.Add("LineStartCap", GetLineStartCapStyle);
            dictFlagToFunction.Add("LineEndCap", GetLineEndCapStyle);
            dictFlagToFunction.Add("HorizontalAlign", GetHAlignStyle);
            dictFlagToFunction.Add("VerticalAlign", GetVAlignStyle);
            dictFlagToFunction.Add("FillPatternColor",GetFillPatternColorStyle);
            dictFlagToFunction.Add("FillPatternStyle", GetFillPatternStyle); 
            dictFlagToFunction.Add("TextWrap", GetTextWrapStyle);
            dictFlagToFunction.Add("Indent", GetIndentStyle);
            dictFlagToFunction.Add("Padding", GetPaddingStyle);
            dictFlagToFunction.Add("RotateAngle", GetRotateAngleStyle);
            
            #region Union Styles

            //  FontStyleAll = FontStyleBold | FontStyleItalic | FontStyleStrikethrough | FontStyleUnderline,
            dictFlagToFunction.Add("FontStyleAll", GetUnUsedUnionStyle);
            // FontAll = FontName | FontSize | FontStyleAll,
            dictFlagToFunction.Add("FontAll", GetUnUsedUnionStyle);
            //LineAll = LineColor | LineStyle | LineWeight | LineStartCap | LineEndCap,
            dictFlagToFunction.Add("LineAll", GetUnUsedUnionStyle);
            // LayoutAll = TextWrap | Padding | RotateAngle
            dictFlagToFunction.Add("LayoutAll", GetUnUsedUnionStyle);
            // AlignAll = HorizontalAlign | VerticalAlign,
            dictFlagToFunction.Add("AlignAll", GetUnUsedUnionStyle);
            // FillPattern = FillPatternColor | FillPatternStyle,
            dictFlagToFunction.Add("FillPattern", GetUnUsedUnionStyle);
            // BackAll = BackColor | FillPattern
            dictFlagToFunction.Add("BackAll", GetUnUsedUnionStyle);
            // All = FontAll | TextColor | BackAll | LineAll | AlignAll | LayoutAll,
            dictFlagToFunction.Add("All", GetUnUsedUnionStyle);
            
            #endregion Union Styles
        }

        #region Dictionary GetStyleFunctions

        #region Font Styles

        protected string GetFontNameStyle(WorksheetRangeStyle cellStyle)
        {
            if(cellStyle.FontName.Contains(" "))
                return string.Format("font-family:\"{0}\";", cellStyle.FontName);
            else
                return string.Format("font-family:{0};", cellStyle.FontName);
        } // end of GetFontNameStyle()

        protected string GetFontSizeStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("font-size:{0};", cellStyle.FontSize);

        } // end of GetFontSizeStyle()

        protected string GetFontBoldStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("font-weight:bold;");
        } // end of GetFontBoldStyle()

        protected string GetFontItalicStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("font-style: italic;");
        } // end of GetFontItalicStyle()

        protected string GetFontUnderlineStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("text-decoration: underline;");
        } // end of GetFontUnderlineStyle()

        protected string GetFontStrikethroughStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("text-decoration: line-through;");
        } // end of GetFontStrikethroughStyle()

        #endregion Font Styles

        #region TextColor and BackColor Styles

        protected string GetTextColorStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("color:#{0};", cellStyle.TextColor.ToStringHex().Substring(2));
        } // end of GetTextColorStyle()

        protected string GetBackColorStyle(WorksheetRangeStyle cellStyle)
        {
            return string.Format("background:#{0};", cellStyle.BackColor.ToStringHex().Substring(2));
        } // end of GetBackColorStyle()

        #endregion TextColor and BackColor Styles

        #region Line Styles

        protected string GetLineColorStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // string.Format("\r\n")
        } // end of GetLineColorStyle()

        protected string GetLineStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // string.Format("\r\n")
        } // end of GetLineStyle()

        protected string GetLineWeightStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // string.Format("\r\n")
        } // end of GetLineWeightStyle()

        protected string GetLineStartCapStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // string.Format("\r\n")
        } // end of GetLineStartCapStyle()

        protected string GetLineEndCapStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // string.Format("\r\n")
        } // end of GetLineEndCapStyle()

        #endregion Line Styles
                   
        #region Text Vertical and Horizontal Align Styles

        protected string GetHAlignStyle(WorksheetRangeStyle cellStyle)
        {
            if (cellStyle.HAlign == ReoGridHorAlign.Center)
                return "text-align:center;";
            else if (cellStyle.HAlign == ReoGridHorAlign.Right)
                return "text-align:right;";
            else if (cellStyle.HAlign == ReoGridHorAlign.Left)
                return "text-align:left;";
            else
                return "";
        } // end of GetHAlignStyle()

        protected string GetVAlignStyle(WorksheetRangeStyle cellStyle)
        {
            if (cellStyle.VAlign == ReoGridVerAlign.Top)
                return "vertical-align:top;";
            else if (cellStyle.VAlign == ReoGridVerAlign.Middle)
                return "vertical-align:middle;";
            else if (cellStyle.VAlign == ReoGridVerAlign.Bottom)
                return "vertical-align:bottom;";
            else
                return "";
        } // end of GetVAlignStyle()


        #endregion Text Vertical and Horizontal Align Styles

        #region Fill Pattern Styles

        protected string GetFillPatternColorStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // unimplemented right now
        } // end of GetFillPatternColorStyle()

        protected string GetFillPatternStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // unimplemented right now
        } // end of GetFillPatternStyle()

        #endregion Fill Pattern Styles

        #region Text Wrap, Indenting Padding, and Rotation Styles

        protected string GetTextWrapStyle(WorksheetRangeStyle cellStyle)
        {
            if (cellStyle.TextWrapMode == TextWrapMode.BreakAll)
                return ""; // unimplemented right now
            else if (cellStyle.TextWrapMode == TextWrapMode.NoWrap)
                return ""; // unimplemented right now
            else if (cellStyle.TextWrapMode == TextWrapMode.WordBreak)
                return ""; // unimplemented right now
            else
                return "";
        } // end of GetTextWrapStyle()

        protected string GetIndentStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // unimplemented right now
        } // end of GetIndentStyle()

        protected string GetPaddingStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // unimplemented right now
        } // end of GetPaddingStyle()

        protected string GetRotateAngleStyle(WorksheetRangeStyle cellStyle)
        {
            return ""; // unimplemented right now
        } // end of GetRotateAngleStyle()
        
        #endregion Text Wrap, Indenting Padding, and Rotation Styles

        protected string GetUnUsedUnionStyle(WorksheetRangeStyle cellStyle)
        {
            return "";
        } // end of GetUnUsedUnionStyle()

        #endregion Dictionary GetStyleFunctions
        
        /// <summary>
        /// We have to build the full style string before we can compare it to our existing list
        /// </summary>
        /// <param name="currRow"></param>
        /// <param name="currCol"></param>
        /// <returns></returns>
        protected HTMLStyle BuildStyleString(int currRow, int currCol)
        {
         
            WorksheetRangeStyle cellStyle = _currWorksheet.GetCellStyles(currRow, currCol);
            HTMLStyle newStyle = new HTMLStyle(cellStyle.Flag);
            
            
            List<string> enumFlags = new List<string>();

            for (int i = 0; i < _enumNames.Length; i++)
            {
                if (cellStyle.HasStyle((PlainStyleFlag)Enum.Parse(typeof(PlainStyleFlag), _enumNames[i])))
                {
                    // instead of adding the flag to a string list insead call the dictionary
                    // this line is for debugging and will be commented out soon
                    enumFlags.Add(_enumNames[i]);

                    string strNewStyle;
                    // using the string flag as key to dictionary function to call and create html style for that flag
                    strNewStyle = dictFlagToFunction[_enumNames[i]](cellStyle);
                    if (strNewStyle.Length >0)
                    {// add to our HTMLStyle object
                        newStyle.Add(strNewStyle);
                    }
                    
                }
               
            }
            // finished creating the style that we may or maynot even need
           // FlexibleMessageBox.Show(string.Format("Styles for [{0}.{1}]\r\n{2}", currRow, currCol, newStyle.StyleString));
            return newStyle;
        }

        protected void GetCellStylesAndConvert(int currRow, int currCol, XElement newCell)
        {
            
            List<string> enumFlags = new List<string>();

            HTMLStyle newStyle;

             newStyle =  BuildStyleString(currRow, currCol );

           // FlexibleMessageBox.Show(newStyle.StyleString);
            // check to see if style already exists if not add it, if so then skip the additon and set new cell to correct style#
            int styleIndex;
            styleIndex = _listHTMLStyles.FindIndex(x => x.Equals(newStyle));
            // not found
            if (styleIndex == -1)
            {
                // since list is zero based, before we add new style its count is next availabe that we will fill
                styleNum = _listHTMLStyles.Count;

                // add new unknown style to HTMLStyle list
                _listHTMLStyles.Add(newStyle);  // used strictly for comparions of style strings


                // add the new unknown style to the style element list
                // used to generate the actual html 
                // _listStyles.Add(new XElement("style", new XAttribute("type", "text/css"), string.Format("\r\n.style{0} {{ {1} }}", styleNum, newStyle.StyleString)));

                // this builds the content inside the <style> </style>tags
                _sbStringStylesCombined.AppendLine(string.Format("\r\n.style{0} {{ {1} }}", styleNum, newStyle.StyleString));

              //  FlexibleMessageBox.Show(string.Format("Created Style#{0} with styles\r\n{1}||end", styleNum, newStyle.StyleString));
                
                
            }
            else
            {
                styleNum = styleIndex;
            }
          //  FlexibleMessageBox.Show(string.Format("Adding Cell[{0},{1}] with style#{2} which is {3}", currRow, currCol, styleNum, _listHTMLStyles[styleNum].StyleString));
            // add cell with appropriate style#
            newCell.Add(new XAttribute("class", string.Format("style{0}", styleNum)));
        
        } // end of GetCellStylesAndConvert()

        protected bool CopyCellValue(int currRow, int currCol, XElement newCell, bool bPreviewTextSet, bool bCreateNewStyle)
        {
            if (_currWorksheet.Cells[currRow, currCol].Data != null)
            {
                newCell.Value = _currWorksheet.Cells[currRow, currCol].Data.ToString();
                
                if (!bPreviewTextSet)
                {
                    strPreviewText = newCell.Value;
                    bPreviewTextSet = true;
                }

            }
            else // if no value then assign an empty value
                newCell.Value = "";


            if (bCreateNewStyle)
                GetCellStylesAndConvert(currRow, currCol, newCell);
            else
             newCell.Add(new XAttribute("class", string.Format("style{0}", styleNum)));
            

            return bPreviewTextSet;

        } // end of CopyCellValue()
        
        protected virtual void ParseSelectedRange()
        {
            // start at top left of the selection range
            int currRow = _selRange.Row;
            int currCol = _selRange.Col;

            short colSpan = 0;
            short rowSpan = 0;
            bool bPreviewTextSet = false;
            bool bCreateNewStyle = false;

            WorksheetRangeStyle prevStyle = null;

            for (currRow = _selRange.Row; currRow <= _selRange.EndRow; currRow++)
            {
                // create a new row element tr for each row
                XElement newRow = new XElement("tr", new XAttribute("row-number", (currRow + 1)));

                for (currCol = _selRange.Col; currCol <= _selRange.EndCol; currCol++)
                {
                    //XElement newCell = new XElement("td");
                    // if cell is merged and doesn't exist skip it
                    if (!_currWorksheet.IsValidCell(currRow, currCol))
                    {
                      //  newCell.Value = "";
                      //  newRow.Add(newCell);
                        continue;

                    }
                    
                    XElement newCell = new XElement("td");
                    WorksheetRangeStyle currStyle = null;
                    if (prevStyle != null)
                    {
                        currStyle = _currWorksheet.GetCellStyles(currRow, currCol);

                        if (currStyle != prevStyle)
                        {
                            // we need to create a new style then!
                            bCreateNewStyle = true;

                        }
                    }

                    else
                    {
                        bCreateNewStyle = true;
                    }
                    prevStyle = currStyle;

                    

                    // create new cell after checking to verify it exists
                    //XElement newCell = new XElement("td");
                    // see if its merged with other cells
                    if (_currWorksheet.Cells[currRow, currCol].IsMergedCell)
                    {
                        // is it merged accross the row ie multiple columns in the row 
                        colSpan = _currWorksheet.Cells[currRow, currCol].GetColspan();

                        // is it merged down the column ie multiple rows in the column
                        rowSpan = _currWorksheet.Cells[currRow, currCol].GetRowspan();

                        bPreviewTextSet = CopyCellValue(currRow, currCol, newCell, bPreviewTextSet, bCreateNewStyle);

                        // add colspan attribute if needed
                        if (colSpan > 1)
                        {
                            newCell.Add(new XAttribute("colspan", colSpan.ToString()));
                            currCol += colSpan;
                        }

                        // add rowspan attribute if needed
                        if (rowSpan > 1)
                            newCell.Add(new XAttribute("rowspan", rowSpan.ToString()));



                    }
                    else // wasn't a merged cell, just need to copy its value then
                    {
                        bPreviewTextSet = CopyCellValue(currRow, currCol, newCell, bPreviewTextSet, bCreateNewStyle);
                        
                    }
                   
                    
                    // add cell to the row
                    newRow.Add(newCell);
                } // end of loop through all columns in that row range
             
                // add row to the list of rows we are keeping track of
                _listRows.Add(newRow);

            } // end of loop through all rows in the range
            
        } // end of ParseSelectedRange()

        protected void GenerateTableElementRows()
        {
            for (int row = 0; row < _listRows.Count; row++)
            {
                //_sb.AppendLine(_listRows[row].ToString());
                _table.Add(_listRows[row]);
            }

        } // end of GenerateTableRows()

        protected void BuildDocString()
        {
            int pos; // used to get char index in string

            GenerateTableElementRows();
            
            // force creation of opening and closing tags
            _body.Value = "";

            //<-------  Hardcoded style to get borders around cells, need better workaround for flexability --->
           _sbStringStylesCombined.AppendLine("td { border: 1px solid gray; border-collapse:collapse;}");

            // _listStyles.Add(new XElement("style", new XAttribute("type", "text/css"), string.Format("\r\n.style{0} {{ {1} }}", styleNum, newStyle.StyleString)));
            _style = new XElement("style", new XAttribute("type", "text/css"), _sbStringStylesCombined.ToString() );
            _head.Add(_style);
            
            
            _html.Add(_head);
            _html.Add(_body);

            // grab position of the opening body tag and save it 
             pos = _html.ToString().LastIndexOf("<body>");
            
            // calculate this position before adding the table element (shorter string to parse )so we can update the preHeader info
            strStartFragPos = (nPreHeaderLength + pos).ToString().PadLeft(10, '0');

            // add table element to the body element
            _body.Add(_table);
            
            // convert the hmtl element to a string at this point after adding the table element
            _sbHTML.Append(_html.ToString());
            
            // insert our fragment tag here since it doesn't have a same closing tag
            _sbHTML.Insert(pos+6, strPreFragStart);
            

            pos = _sbHTML.ToString().LastIndexOf("</body");
            // calculate this position so we can update the preHeader info
            strEndFragPos = (nPreHeaderLength + pos).ToString().PadLeft(10, '0');

            // insert our closing tag for html fragment to get in correct clipboard format
            _sbHTML.Insert(pos, strPostFragStop);

            
          //  FlexibleMessageBox.Show(_sbHTML.ToString());
                        
         
        } // end of BuildDocString()

              
        public void BuildFixedLengthPreHeader()
        {
             strStartHTMLPos = nPreHeaderLength.ToString().PadLeft(10,'0');
             strStartHTMLPos = strStartHTMLPos.PadLeft(10, '0');
             strEndHTMLPos = (_sbHTML.Length + nPreHeaderLength).ToString().PadLeft(10,'0');

            if (_sbPreHeader == null)
                _sbPreHeader = new StringBuilder(100);
            else
                _sbPreHeader.Clear();

            _sbPreHeader.Append((pHeaderPart1 + pHeaderPart2 + strStartHTMLPos));
            _sbPreHeader.Append((pHeaderPart3 + strEndHTMLPos));
            _sbPreHeader.Append((pHeaderPart4 + strStartFragPos));
            _sbPreHeader.Append((pHeaderPart5 + strEndFragPos));

          //  FlexibleMessageBox.Show(_sbPreHeader.ToString());

        } // end of BuildFixedLengthPreHeader()

        protected void BuildClipboardFormatString()
        {
            if (_sbClipboardFormat == null)
                _sbClipboardFormat = new StringBuilder((_sbPreHeader.Length + _sbHTML.Length + 1));
            else
                _sbClipboardFormat.Clear();

            _sbClipboardFormat.Append(_sbPreHeader.ToString());
            _sbClipboardFormat.Append(_sbHTML.ToString());
            strHTMLClipboardFormat = _sbClipboardFormat.ToString();
            //FlexibleMessageBox.Show(strHTMLClipboardFormat);

        } // end of BuildClipboardFormatString()

        protected string GenerateHTML(ReoGridControl rgc)
        {
            _rgc = rgc;
            
            // 1st determine the length/size of the selected range/cells to convert
            GetCurrentWorksheetSelectedRange();

            // then start trying to parse! get formats etc...
            ParseSelectedRange();
            BuildDocString();
            BuildFixedLengthPreHeader();
            BuildClipboardFormatString();
            return strHTMLClipboardFormat;
        } // end of GenerateHTML()

        public void PasteHTMLFormatToClipboard(ReoGridControl rgc)
        {
            if(_sbStringStylesCombined == null)
                _sbStringStylesCombined = new StringBuilder(300);
            else
            _sbStringStylesCombined.Clear();

            // build the HTML string with preheader and postheader info
            GenerateHTML(rgc);

            DataObject doReport = new DataObject();
           // FlexibleMessageBox.Show(strPreviewText);
            Clipboard.Clear();
            doReport.SetData(DataFormats.UnicodeText, strPreviewText);
            doReport.SetData(DataFormats.Text, strPreviewText);
            doReport.SetData(DataFormats.Html, strHTMLClipboardFormat);
            Clipboard.SetDataObject(doReport);
            
        } // end of PasteHTMLFormatToClipboard()

    } // end of class HTMLClipboardFormatGenerator


    /// <summary>
    /// Used to store the HTML class styles
    /// </summary>
    public class HTMLStyle : IEquatable<HTMLStyle>
    {
        protected PlainStyleFlag _psfNumber = 0;
        protected List<string> _styles = new List<string>();
        protected string _styleName = "";
        protected StringBuilder _sbStyle = new StringBuilder(50);

        #region PublicProperties

        public PlainStyleFlag PSFNumber
        {
            get { return _psfNumber; }
        
        }

        public List<string> Styles
        {
            get { return _styles; }

        }

        public string StyleString
        {
            get { return _sbStyle.ToString();   }
        }

        #endregion Public Properties

        public HTMLStyle(PlainStyleFlag psf)
        {
            _psfNumber = psf;

        }
     

        public void Add(string strNewStyle)
        {
            if (strNewStyle != null)
            {
                _styles.Add(strNewStyle);

                _sbStyle.AppendLine(strNewStyle);
            }
        }

        public void Clear()
        {
            _styles.Clear();
            _sbStyle.Clear();
        }

        public bool Equals(HTMLStyle other)
        {
            // if we are pointing to same item they must be equal
            if (ReferenceEquals(this, other))
                return true;

            // if other object is nothing they cannot be equal
            if (ReferenceEquals(null, other))
                return false;

            // now we do custom comparisons

            // are the style number(flags set) the same
            // if not then they cannot be equal as will have different 
            // sized lists of style strings with different flags set
            if (PSFNumber != other.PSFNumber)
                return false;
            // should never fail here but just in case
            if (Styles.Count != other.Styles.Count)
                return false;

            for (int i = 0; i < Styles.Count; i++)
            {
                // compare each string style to other string style
                // if strings don't match then return false
                if (Styles[i] != other.Styles[i])
                    return false;

            }
            return true; // objects have same list of html style strings with same values, same flag#

        } // end of Equals()
        
        public override bool Equals(object obj)
        {
            return Equals(obj as HTMLStyle);
        }


    } // end of class HTMLStyle
} // end of namespace

I love XElement! That made HTML tag generation so easy.
Please feel free to modify, fix, upgrade or improve as possible!

Fletch

Offline

#2 2016-12-14 03:00:01

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Class for Adding Partial Support on Copy to Clipboard in HTMLFormat

Thanks Fletch for share this nice feature! I will try to add it into the source code repository of ReoGrid.

Offline

#3 2017-08-18 00:10:39

asparatu
Member
Registered: 2014-08-20
Posts: 196

Re: Class for Adding Partial Support on Copy to Clipboard in HTMLFormat

Hello Jing,

I was looking for something like this.. If wanted to add this to source code where would i add it? or have you added it already?

Shane

Offline

#4 2017-08-21 01:44:08

Jingwood
Moderator
From: jing at reogrid.net
Registered: 2014-06-03
Posts: 615

Re: Class for Adding Partial Support on Copy to Clipboard in HTMLFormat

Hi Shane,

The source code can be checked out from GitHub:
https://github.com/unvell/ReoGrid

It would be great if you can add it!

Offline

Board footer

Powered by FluxBB