You are not logged in.
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.
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
to here
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
Thanks Fletch for share this nice feature! I will try to add it into the source code repository of ReoGrid.
Offline
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
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