在office上選取物件利用ctrl+c複製物件到clipboard內,
並在picturebox控制項上利用ctrl+v將物件從clipboard取出,
並以圖片形式顯示在picturebox上,
最後將picturebox上的image存成圖片檔。
首先先記錄一下如何判斷鍵盤的組合鍵,如下:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyData)
{
case (Keys.Control | Keys.V):
// do something
break;
}
}
接下來的重點是從clipboard內取出物件時必須知道它支援那些格式,
我們可以利用下面的方式知道該物件所支援的格式有那些:
foreach (string format in Clipboard.GetDataObject().GetFormats())
{
// do something
}
也有一些簡便的方式,例如Clipboard.ContainsText()或Clipboard.ContainsImage()等可以判斷。再來我們準備一些method來從clipboard中取出office中大部份常見的格式。
Bitmap格式的物件,我們都能用下面的方式取得image:
public void CatchBitmap()
{
this.pictureBox1.Image = (Bitmap)Clipboard.GetImage();
}
這裡遇到比較麻煩的困難點是EnhancedMetafile格式,
必須要用win32裡的API去取得系統的clipboard來使用,方式如下:
public const uint CF_METAFILEPICT = 3;
public const uint CF_ENHMETAFILE = 14;
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool CloseClipboard();
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetClipboardData(uint format);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool IsClipboardFormatAvailable(uint format);
public void CatchEMF()
{
if (OpenClipboard(this.Handle)) {
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
IntPtr ptr = GetClipboardData(CF_ENHMETAFILE);
if (!ptr.Equals(new IntPtr(0)))
{
Metafile metafile = new Metafile(ptr, true);
//Set the Image Property of PictureBox
this.pictureBox1.Image = metafile;
}
}
CloseClipboard();
}
}
再來如果copy放進clipboard內的是純文字物件的話,
就必須要用Graphics來drawing string才能產生圖檔,如下:
public void DrawString()
{
String sImageText = Clipboard.GetText();
Bitmap objBmpImage = new Bitmap(1, 1);
int intWidth = 0;
int intHeight = 0;
// Create the Font object for the image text drawing.
Font objFont =
new Font("Arial", 20, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Pixel);
// Create a graphics object to measure the text's width and height.
Graphics objGraphics = Graphics.FromImage(objBmpImage);
// This is where the bitmap size is determined.
intWidth = (int)objGraphics.MeasureString(sImageText, objFont).Width;
intHeight = (int)objGraphics.MeasureString(sImageText, objFont).Height;
// Create the bmpImage again with the correct size for the text and font.
objBmpImage = new Bitmap(objBmpImage, new Size(intWidth, intHeight));
// Add the colors to the new bitmap.
objGraphics = Graphics.FromImage(objBmpImage);
// Set Background color
objGraphics.Clear(Color.White);
objGraphics.SmoothingMode = SmoothingMode.AntiAlias;
objGraphics.TextRenderingHint = TextRenderingHint.AntiAlias;
objGraphics.DrawString(sImageText, objFont,
new SolidBrush(Color.FromArgb(102, 102, 102)), 0, 0);
objGraphics.Flush();
this.pictureBox1.Image = objBmpImage;
}
接下來下面要講解的功能是如何把在excel內選取的cells自動轉換成對應的chart圖,
基本上複製的cells放進clipboard本身就支援Bitmap格式,
但直接取用會直接像剪貼那樣,如果要轉換成對應的chart圖則必須再行判斷,
這裡是利用Microsoft.Office.Interop.Excel來轉換,範例碼如下:
public void Convert()
{
IDataObject iData = Clipboard.GetDataObject();
String cellArea = (String)iData.GetData(DataFormats.Text);
String[] rows = cellArea.Split(new Char[] { '\n' });
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
int rowLength = rows.Length;
int rowCount = 1;
int cellCount = 1;
int maxCellCount = 1;
foreach (String line in rows)
{
if (rowCount == rowLength)
{
break;
}
String[] cells = line.Split(null);
int cellLength = cells.Length;
foreach (String cell in cells)
{
if (cellCount == cellLength)
{
break;
}
if (cellCount > maxCellCount)
{
maxCellCount++;
}
xlWorkSheet.Cells[rowCount, cellCount] = cell;
cellCount++;
}
rowCount++;
cellCount = 1;
}
Excel.Range chartRange;
Excel.ChartObjects xlCharts = (Excel.ChartObjects)xlWorkSheet.ChartObjects(Type.Missing);
Excel.ChartObject myChart = (Excel.ChartObject)xlCharts.Add(10, 80, 300, 250);
Excel.Chart chartPage = myChart.Chart;
rowCount--;
maxCellCount--;
String endCorner = map.ElementAt(maxCellCount).Value;
endCorner = endCorner + rowCount.ToString();
// endCorner的格式例如:c7,就是cells右下角的範圍邊界點
chartRange = xlWorkSheet.get_Range("A1", endCorner);
chartPage.SetSourceData(chartRange, misValue);
// 設定繪製的chart圖型式
chartPage.ChartType = Excel.XlChartType.xlColumnClustered;
chartPage.CopyPicture(Excel.XlPictureAppearance.xlScreen,
Excel.XlCopyPictureFormat.xlBitmap,
Excel.XlPictureAppearance.xlScreen);
xlWorkBook.Close(false, false, misValue);
}
產生的chart圖會利用copy放進clipboard內。使用畫面如下,紅色框部份就是被選取的cells,當在picturebox上按下ctrl+v時,
就會利用office元件繪製chart圖:
最後就是整理一些條件判斷式,來處理當遇到什樣格式時要執行那一個method比較恰當:
// 一般的圖檔
if (this.formatList.Contains("Bitmap") && !this.formatList.Contains("Text"))
{
CatchBitmap();
}
// excel的cells欄位集合
else if (this.formatList.Contains("Bitmap") && this.formatList.Contains("Text"))
{
// if want to create chart
Convert();
// offic 2003
CatchBitmap();
// offic 2007
CatchEMF();
}
// 純粹選取文字
else if (!this.formatList.Contains("Bitmap") && this.formatList.Contains("Text"))
{
DrawString();
}
// excel2003的chart,只有emf格式,最後再處理
else if (this.formatList.Contains("EnhancedMetafile"))
{
CatchEMF();
}

沒有留言:
張貼留言