如何将文本从剪贴板拆分为DataGridView [英] How to split text from the Clipboard into a DataGridView

查看:48
本文介绍了如何将文本从剪贴板拆分为DataGridView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将要从网站复制的文本拆分为DataGridView控件.我要复制的文字尤其来自Binance网站,其格式如下:

我的DataGridView控件包含9列:
Date Pair Type Side Average Price 已执行金额总计.

复制

03-17 10:55:03 DOGE/EUR买入限价0.04816 0.04816 11,740.0 11,740.8 565.39840

我想将其粘贴到我的DataGridView中以填充相对的列,但是,当我粘贴它时,仅填充了Date列的单元格.有没有办法分割文字?


剪贴板内容的二进制表示形式:

  30 33 2d 31 37 20 32 32 3a 35 37 3a 32 38 0d 0a44 4f 47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d0a 53 65 6c 6c 0d 0a 30 2e 30 34 38 37 38 0d 0a30 2e 30 34 38 37 38 0d 0a 33 30 2c 35 32 36 2e30 0d 0a 33 30 2c 35 32 36 2e 30 0d 0a 31 2c 3438 39 2e 30 35 38 32 38 0d 0a 30 33 2d 31 37 2031 33 3a 31 39 3a 33 39 0d 0a 44 4f 47 45 2f 4555 52 0d 0a 4c 69 6d 69 74 0d 0a 42 75 79 0d 0a30 2e 30 34 38 30 30 0d 0a 30 2e 30 34 38 30 300d 0a 31 2c 31 30 30 2e 38 0d 0a 31 2c 31 30 302e 38 0d 0a 35 32 2e 38 33 38 34 30 0d 0a 30 332d 31 37 20 31 30 3a 35 35 3a 30 33 0d 0a 44 4f47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d 0a 4275 79 0d 0a 30 2e 30 34 38 31 36 0d 0a 30 2e 3034 38 31 36 0d 0a 31 31 2c 37 34 30 2e 38 0d 0a31 31 2c 37 34 30 2e 38 0d 0a 35 36 35 2e 34 3336 39 33 0d 0a 30 33 2d 31 37 20 31 30 3a 33 313a 35 33 0d 0a 44 4f 47 45 2f 45 55 52 0d 0a 4c69 6d 69 74 0d 0a 42 75 79 0d 0a 30 2e 30 34 3832 30 0d 0a 30 2e 30 34 38 32 30 0d 0a 31 31 2c39 37 30 2e 33 0d 0a 31 31 2c 39 37 30 2e 33 0d0a 35 37 36 2e 39 36 38 34 36 

Edit2:
第二个二进制文件

  30 33 2d 31 37 20 32 32 3a 35 37 3a 32 38 0d 0a44 4f 47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d0a 53 65 6c 6c 0d 0a 30 2e 30 34 38 37 38 0d 0a30 2e 30 34 38 37 38 0d 0a 33 30 2c 35 32 36 2e30 0d 0a 33 30 2c 35 32 36 2e 30 0d 0a 31 2c 3438 39 2e 30 35 38 32 38 

解决方案

在此处发布的示例十六进制数据中,从Web表复制的数据源中的所有字段均由 0x0D 0x0A 分隔( \ r \ n ,即 ChrW(13)ChrW(10),即 vbCrLf ).行也是.

要解析此格式,您需要知道有多少个字段组成一个行,以确定回车+换行符何时定义了字段或行的边界.
在此处显示的示例中,数据源由 9 字段组成,因此我将保留此引用作为要考虑的格式.
当然,如果需要,可以将简单的解析器调整为其他格式.

将源数据从WebBrowser复制到剪贴板后,我们可以使用


动画中显示的Form和DataGridView可以在此PasteBin中找到:
表单类+设计器

ContextMenuStrip是使用自定义 ToolStripProfessionalRenderer ,它使用自定义 ProfessionalColorTable 附加到可替换颜色定义类(可以在运行时或设计时替换为另一个).
用于自定义的所有对象都发布在这里:
在ContextMenuStrip中更改图像和文本之间的空间

I would like to split the text I'm copying from a website into a DataGridView control. The text I'm copying, in particular, comes from Binance website and the format its the following:

My DataGridView control contains 9 Columns:
Date, Pair, Type, Side, Average, Price, Executed, Amount, Total.

Copying

03-17 10:55:03 DOGE/EUR Limit Buy 0.04816 0.04816 11,740.0 11,740.8 565.39840

I want to paste it into my DataGridView in order to fill the relative Columns, but, when I'm pasting it, just the cell of Date column is being filled. Is there a way to split the text?

Edit:
Binary representation of the Clipboard content:

30 33 2d 31 37 20 32 32 3a 35 37 3a 32 38 0d 0a
44 4f 47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d
0a 53 65 6c 6c 0d 0a 30 2e 30 34 38 37 38 0d 0a
30 2e 30 34 38 37 38 0d 0a 33 30 2c 35 32 36 2e
30 0d 0a 33 30 2c 35 32 36 2e 30 0d 0a 31 2c 34
38 39 2e 30 35 38 32 38 0d 0a 30 33 2d 31 37 20
31 33 3a 31 39 3a 33 39 0d 0a 44 4f 47 45 2f 45
55 52 0d 0a 4c 69 6d 69 74 0d 0a 42 75 79 0d 0a
30 2e 30 34 38 30 30 0d 0a 30 2e 30 34 38 30 30
0d 0a 31 2c 31 30 30 2e 38 0d 0a 31 2c 31 30 30
2e 38 0d 0a 35 32 2e 38 33 38 34 30 0d 0a 30 33
2d 31 37 20 31 30 3a 35 35 3a 30 33 0d 0a 44 4f
47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d 0a 42
75 79 0d 0a 30 2e 30 34 38 31 36 0d 0a 30 2e 30
34 38 31 36 0d 0a 31 31 2c 37 34 30 2e 38 0d 0a
31 31 2c 37 34 30 2e 38 0d 0a 35 36 35 2e 34 33
36 39 33 0d 0a 30 33 2d 31 37 20 31 30 3a 33 31
3a 35 33 0d 0a 44 4f 47 45 2f 45 55 52 0d 0a 4c
69 6d 69 74 0d 0a 42 75 79 0d 0a 30 2e 30 34 38
32 30 0d 0a 30 2e 30 34 38 32 30 0d 0a 31 31 2c
39 37 30 2e 33 0d 0a 31 31 2c 39 37 30 2e 33 0d
0a 35 37 36 2e 39 36 38 34 36

Edit2:
Second binary

30 33 2d 31 37 20 32 32 3a 35 37 3a 32 38 0d 0a
44 4f 47 45 2f 45 55 52 0d 0a 4c 69 6d 69 74 0d
0a 53 65 6c 6c 0d 0a 30 2e 30 34 38 37 38 0d 0a
30 2e 30 34 38 37 38 0d 0a 33 30 2c 35 32 36 2e
30 0d 0a 33 30 2c 35 32 36 2e 30 0d 0a 31 2c 34
38 39 2e 30 35 38 32 38

解决方案

In the sample Hex data posted here, all Fields in the data source, copied from a Web Table, are separated by 0x0D 0x0A (\r\n, i.e. ChrW(13) ChrW(10), i.e. vbCrLf). So are the Rows.

To parse this format, you need to know how many Fields compose a Row, to determine when a Carriage Return+Line Feed defines the boundaries of a Field or a Row.
In the sample presented here, the data source is compose of 9 Fields, so I'm keeping this reference as the Format to consider.
Of course the simple parser can be adapted to a different format, in case it's needed.

After the source data has been copied to the Clipboard from a WebBrowser, we can retrieve the data as text using Clipboard.GetText().
Here, I'm trimming any ChrW(13) ChrW(10) ChrW(32) from the beginning and end of the text, in case some of these were added by mistake while selecting the HTML text.

The parser retrieves all parts from the text and checks whether the resulting array of strings is a multiple of 9. If not, throws an exception (we cannot parse this format, it's assumed that a Row will contain 9 Fields).

The array of strings is then converted to an Object() array, containing all the values already converted to the destination Type. The array is the used as the source of a new Row of the DataTable - which is attached to a BindingSource - used as the source of data for the DataGridView.
The DataTable also defines a Column that is used as an auto-incrementing index.


In the Form Constructor, the Data Source and the DataGridView are initialized calling the InitializeDataSource() and InitializeBinanceUI() methods.
These method initialize the DataTable and the base Format of the DataGridView Columns, plus and event handler used to change the Color of the text one of the Columns.

Note: The DataGridView here is named dgvBinance. Add one in the Form designer and rename it like this.

Imports System.ComponentModel
Imports System.Data
Imports System.Globalization

Private binanceSource As BindingSource = Nothing
Private binanceData As DataTable = Nothing

Public Class SomeForm
    Public Sub New()
        InitializeComponent()
        ' [...]
        InitializeDataSource()
        InitializeBinanceUI()
    End Sub

    Private Sub InitializeDataSource()
        binanceData = New DataTable("BinanceData")
        binanceData.Columns.Add(New DataColumn() With {
            .ColumnName = "Index",
            .AutoIncrement = True,
            .AutoIncrementSeed = 1,
            .AutoIncrementStep = 1
        })

        binanceData.Columns.Add("Date", GetType(Date))
        binanceData.Columns.Add("Pair", GetType(String))
        binanceData.Columns.Add("Type", GetType(String))
        binanceData.Columns.Add("Side", GetType(String))

        binanceData.Columns.Add("Average", GetType(Decimal))
        binanceData.Columns.Add("Price", GetType(Decimal))
        binanceData.Columns.Add("Executed", GetType(Decimal))
        binanceData.Columns.Add("Amount", GetType(Decimal))
        binanceData.Columns.Add("Total", GetType(Decimal))
    End Sub

    Private Sub InitializeBinanceUI()
        AddHandler dgvBinance.CellFormatting, AddressOf dgvBinanceCellFormatting
        binanceSource = New BindingSource(binanceData, "")
        dgvBinance.DataSource = binanceSource
        dgvBinance.Columns("Date").DefaultCellStyle.Format = "MM-dd H:mm:ss"
        dgvBinance.Columns("Average").DefaultCellStyle.Format = "N5"
        dgvBinance.Columns("Price").DefaultCellStyle.Format = "N5"
        dgvBinance.Columns("Executed").DefaultCellStyle.Format = "N1"
        dgvBinance.Columns("Amount").DefaultCellStyle.Format = "N1"
        dgvBinance.Columns("Total").DefaultCellStyle.Format = "N5"
    End Sub

    Private Sub dgvBinanceCellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs)
        If e.Value Is Nothing OrElse dgvBinance.Columns(e.ColumnIndex).Name <> "Side" Then Return
        e.CellStyle.ForeColor = If(e.Value.ToString().Equals("Buy"), Color.Green, Color.Red)
    End Sub
End Sub

When you need to paste new Rows into the Control, get the text from the Clipboard and call the parser, passing the text you got from the Clipboard and the DataTable used as DataSource.
The BindingSource that uses the DataTable as source will update the UI.

Dim sourceData = Clipboard.GetText(TextDataFormat.Text)
Dim rowsAdded = BinanceParseCopyData(sourceData, binanceData)

Parser:

Private Function BinanceParseCopyData(input As String, dataSource As DataTable) As Integer
    Dim culture = CultureInfo.InvariantCulture
    input.Trim({ChrW(13), ChrW(10), ChrW(32)})

    Dim allData = input.Split({vbCrLf}, StringSplitOptions.RemoveEmptyEntries)
    If allData.Length Mod 9 <> 0 Then
        Throw New FormatException($"Unexpected Data Format. A Data Row must be composed of 9 Columns. Found {allData.Length}")
    End If

    Dim rowsCount As Integer = 0
    For pos As Integer = 0 To allData.Length - 1 Step 9
        Dim row As Object() = New Object(9) {}
        Array.Copy(allData, pos, row, 1, 9)
        ' row(0) remains null, since the Column at this index is used by 
        ' the DataTable for the automatic indexer (and expects null as value)
        row(1) = Date.ParseExact(row(1).ToString().Trim(), "MM-dd H:mm:ss", culture)
        row(2) = row(2).ToString().Trim()
        row(3) = row(3).ToString().Trim()
        row(4) = row(4).ToString().Trim()
        row(5) = Decimal.Parse(row(5).ToString().Trim(), NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands, culture)
        row(6) = Decimal.Parse(row(6).ToString().Trim(), NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands, culture)
        row(7) = Decimal.Parse(row(7).ToString().Trim(), NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands, culture)
        row(8) = Decimal.Parse(row(8).ToString().Trim(), NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands, culture)
        row(9) = Decimal.Parse(row(9).ToString().Trim(), NumberStyles.AllowDecimalPoint Or NumberStyles.AllowThousands, culture)
        dataSource.Rows.Add(row)
        rowsCount += 1
    Next
    Return rowsCount
End Function

Graphic sample of the results:


The Form and the DataGridView shown in the animation can be found in this PasteBin:
Form class + Designer

The ContextMenuStrip is designed using a custom ToolStripProfessionalRenderer which uses a custom ProfessionalColorTable attached to a replaceable Color definition class (can be replaced with another at run-time or design-time).
All the object used for the customization are posted here:
Change space between Image and Text in ContextMenuStrip

这篇关于如何将文本从剪贴板拆分为DataGridView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆