直接复制DataGridView中的数据,中文会变成乱码
Private Sub DataGridViewX1_KeyPress(sender As System.Object, e As System.Windows.Forms.KeyPressEventArgs) Handles DataGridViewX1.KeyPress
If (AscW(e.KeyChar.ToString()) = 3 AndAlso DataGridViewX1.RowCount > 0) Then
Dim pDataObject As DataObject = DataGridViewX1.GetClipboardContent()
If (pDataObject Is Nothing) Then
Return
End If
Dim pContent As String = pDataObject.GetData(DataFormats.UnicodeText).ToString()
Try
Clipboard.Clear()
Clipboard.SetText(pContent, TextDataFormat.UnicodeText)
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.OkOnly, My.Application.Info.Title)
End Try
End If
End Sub
解决方案1是:手工选择Unicode Text格式方式进行粘贴
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Dim filepath As String = Application.StartupPath & "/" & Now.ToFileTimeUtc & ".xls"
Dim objexcel As New Excel.Application()
Dim objbook As Excel.Workbook = objexcel.Workbooks.Add()
objbook.SaveAs(filepath)
'设置复制模式为:连同行头和表头一起复制
Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
'如果不需要复制行头,就把它隐藏掉
Me.DataGridView1.RowHeadersVisible = False
'选中DataGridView1的所有内容
Me.DataGridView1.SelectAll()
'判断DataGridView1中是否有选中单元格(与上面好像有点矛盾,自行处理)
If Me.DataGridView1.GetCellCount(DataGridViewElementStates.Selected) > 0 Then
Clipboard.SetDataObject(Me.DataGridView1.GetClipboardContent())
End If
'直接在Excel中粘贴
'objexcel.ActiveSheet.paste()
'為防止亂碼。使用選擇性粘貼
'下面這一行,相當于在Excel中點擊右鍵->選擇性粘貼->文本
'objexcel.ActiveSheet.PasteSpecial(Format:="文本", Link:=False, DisplayAsIcon:=False)
'修改为选择性粘贴--> Unicode 文本
objexcel.ActiveSheet.PasteSpecial(Format:="Unicode 文本", Link:=False, DisplayAsIcon:=False)
'选中Excel所有单元格
objexcel.Cells.Select()
'不自动换行
objexcel.Selection.WrapText = False
'自动调整列宽
objexcel.Columns.AutoFit()
'储存
objbook.Save()
'退出
objbook.Close()
objexcel.Quit()
objbook = Nothing
objexcel = Nothing
killexcel()
'提示打开文件
If MessageBox.Show("档案储存在:" & filepath & ",你要打开吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) = Windows.Forms.DialogResult.Yes Then
Process.Start(filepath)
End If
Catch ex As Exception
killexcel()
MsgBox(ex.Message)
End Try
End Sub
'杀掉程序创建的Excel进程
Private Sub killexcel()
Try
For Each proc As Process In Process.GetProcessesByName("EXCEL")
If proc IsNot Nothing AndAlso proc.MainWindowTitle = "" Then
proc.Kill()
End If
Next
Catch ex As Exception
Throw ex
End Try
End Sub
解决方案4:在DatagridView端想办法,让复制的格式本身就是文本格式,这样在粘贴的时候,就无需转化成文本格式了
参考:
最近,用datagridview,发现他已经自带ctrl+C复制功能了,但复制到Excel时出现乱码,必须用选择性粘贴。感觉比较麻烦,所以添加keyup事件来改写ctrl+C功能。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private void ctrlC_KeyUp( object sender, KeyEventArgs e) { //System.Diagnostics.Debug.Print((e.KeyCode==Keys.C).ToString()); //System.Diagnostics.Debug.Print((e.Control).ToString()); if (e.KeyCode == Keys.C && e.Control) { if (sender != null && sender.GetType() == typeof (DataGridView)) { DataGridView dgv = (DataGridView)sender; dgv.RowHeadersVisible = false ; Clipboard.SetText(dgv.GetClipboardContent().GetData(DataFormats.UnicodeText, true ).ToString()); dgv.RowHeadersVisible = true ; } } } |
正常复制下已经没有问题了,但出现一个很怪的问题,当我ctrl C按得很快的时候(准确的说是先释放ctrl键的时候),发现仍然出现乱码,我知道先释放ctrl键应该是进不了我的if里,但为什么自带的ctrl C能正常进行复制呢?难道自带的ctrl C是写在keydown里的?于是,我做了两个实验验证一下:
1、不添加我自己的keyup事件下,用自带ctrl C进行复制,先释放ctrl键,结果是可以复制。(似乎证明自带ctrl C功能,在keydown事件里)
2、不添加我自己的keyup事件下,选择部分cell按ctrl C,不释放,再选择别一组cell,再释放ctrl C,结果是两组cell全部被复制。(似乎证明自带ctrl 功能,在keyup事件里)
这两种情况,出现了不一样的结论,于是我怀疑是不是自带ctrl C功能,把keydown keyup事件都写进了方法。我又试着把上面自己写的ctrl C方法,同时添加给keydown 和keyup,但发现先释放ctrl键的时候仍然是乱码。
也许datagridview自带的功能优先权更高,这我就不太清楚了,但我想知道有没有办法能把自带的ctrl C方法给屏蔽掉。或继承重写这个功能?因为有时按快了ctrl C经常容易出现ctrl先释放的问题,这样就又出现乱码了。
—————————————
System.Windows.Forms.DataGridView控件以数据网络的方法呈现数据,可以非常方便的用它绑定数据源,不需要编辑多少代码就可以实现对数据源的增删改功能。偶然发现它有一个小小的问题,我们用快捷键复制(Ctrl+C/Ctrl+Insert)表格内容后,到常用的办公处理软件(如微软Office系列和Sun的OpenOffice)中粘贴,那么带有Unicode字符的内容会显示会乱码。使用反射工具查看了DataGridView控件对此功能的实现方法,是由于它直接采用了剪贴版类的SetDataObject方法而没有指定其格式,那么它的格式似乎被认为是ANSI的HTML格式+Unicode内容,所以直接粘贴到字处理软件或者表格处理软件(有时,微软Excel会因此无响应)显示出汉字等Unicode字符却成了乱码。
Clipboard.SetDataObject(clipboardContent);
此种情况可以利用“选择性粘贴”将其格式按“无格式文本”粘贴就可以了。
总不要是这样子,我们还可以编写一个DataGridView子类,重写ProcessDataGridViewKey方法,当它在处理“复制”的快捷键时用我们重新实现的ProcessInsertKey来完成任务,将复制剪贴板功能改为Unicode格式的SetText方法即可。代码如下(修改的剪贴板功能在29行):
public class MyDataGridView : DataGridView
{
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override bool ProcessDataGridViewKey(KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Insert:
case Keys.C:
return this.ProcessInsertKey(e.KeyData);
default:
break;
}
return base.ProcessDataGridViewKey(e);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected new bool ProcessInsertKey(Keys keyData)
{
if ((((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == Keys.Control) ||
(((keyData & (Keys.Alt | Keys.Control | Keys.Shift)) == (Keys.Control | Keys.Shift))
&& ((keyData & Keys.KeyCode) == Keys.C)))
&& (this.ClipboardCopyMode != DataGridViewClipboardCopyMode.Disable))
{
DataObject clipboardContent = this.GetClipboardContent();
if (clipboardContent != null)
{
//Clipboard.SetDataObject(clipboardContent);
Clipboard.SetText(clipboardContent.GetData(DataFormats.UnicodeText).ToString());
return true;
}
}
return false;
}
}