如何动态显示多个标签,其值一个在另一个之下而不重复? [英] How can I dynamically display multiple labels with values one below the other without repetations?
问题描述
我正在尝试构建一个搜索excel文件的特定列中的字符串的应用程序,如果找到该字符串,则显示相应的列值Ex Ex:Say我在excel文件列中搜索字符串 N,如果找到我正在搜索的字符串,则显示同一行的E列值。事实是我的代码在第二种形式的多个标签中多次显示单个值。
我尝试过:
FORM1:
I am trying to build an application that searches a string in a specific column of an excel file and if the string is found, display the corresponding column value For Ex: Say I am searching for a string in an excel file column "N", If the string I am searching for is found then display the "E"th Column value of the same row.The thing is that my code is displaying a single value multiple times in multiple labels of second form.
What I have tried:
FORM1:
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office.Interop.Excel
Imports System.Globalization
Imports System.Runtime.InteropServices
Public Class Form1
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim range As Excel.Range
Dim Obj As Object
Dim pass As String
If OpenFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
Dim sr As New System.IO.StreamReader(OpenFileDialog1.FileName)
MessageBox.Show("You have selected" + OpenFileDialog1.FileName)
'sr.Close()
End If
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Open(OpenFileDialog1.FileName)
xlWorkSheet = xlWorkBook.Worksheets("sheet1")
range = xlWorkSheet.UsedRange
For rCnt = 1 To range.Rows.Count
For cCnt = 14 To range.Columns.Count
If xlWorkSheet.Cells(rCnt, cCnt).value = "3" Or xlWorkSheet.Cells(rCnt, cCnt).value = "4" Or xlWorkSheet.Cells(rCnt, cCnt).value = "5" Or xlWorkSheet.Cells(rCnt, cCnt).value = "6" Or xlWorkSheet.Cells(rCnt, cCnt).value = "7" Or xlWorkSheet.Cells(rCnt, cCnt).value = "8" Or xlWorkSheet.Cells(rCnt, cCnt).value = "9" Or xlWorkSheet.Cells(rCnt, cCnt).value = "10" Then
Obj = CType(range.Cells(rCnt, "E"), Excel.Range)
'MessageBox.Show(Obj.value)
Foo = Obj.value
Form2.Show()
End If
Next
Next
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
FORM2:
< br $>
FORM2:
Imports System.Linq
Imports System.Drawing
Public Class Form2
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
Dim label As New Label()
Dim count As Integer = Panel1.Controls.OfType(Of Label)().ToList().Count
label.Location = New Point(10, (25 * count))
'label.Size = New Size(40, 20)
label.Name = "label_" & (count + 1)
label.Text = Foo '& (count + 1)
label.AutoSize = True
Panel1.Controls.Add(label)
Dim button As New Button()
button.Location = New System.Drawing.Point(250, 25 * count)
button.Size = New System.Drawing.Size(60, 20)
button.Name = "Print" & (count + 1)
button.Text = "Print" '& (count + 1)
AddHandler button.Click, AddressOf Button_Click
Panel1.Controls.Add(button)
MessageBox.Show(Foo)
End Sub
Private Sub Button_Click(sender As Object, e As EventArgs)
Dim button As Button = TryCast(sender, Button)
MessageBox.Show(button.Name + " clicked")
End Sub
End Class
MODULE:
MODULE:
Module Module1
Public Foo As String
End Module
推荐答案
你的代码有几个问题。
首先你试图在循环中显示Form2,然后你在无模式状态下显示它。换句话说,在Form2.Show行之后继续处理循环。
@Ralf_Meier给出了一个使用DataGridView [ ^ ]。它简化了所有代码,用于计算控件的大小,位置,将它们添加到集合中。
这是一个工作示例。我还对代码进行了一些其他调整,因此请注意解释原因的评论。
You have a couple of issues with your code.
Firstly you are attempting to show Form2 within the loop and secondly you are showing it in a modeless state. In other words processing of the loop continues after the Form2.Show line.
@Ralf_Meier has given an excellent suggestion of using a DataGridView[^]. It simplifies all of the code for working out the size of the controls, the positions, adding them to a collection.
Here is a working example. I've made some other adjustments to the code as well so watch out for the comments explaining why.
Public Class Form1
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim xlApp As Application
Dim xlWorkBook As Workbook
Dim xlWorkSheet As Worksheet
Dim range As Range
'You can make the OpenFileDialog look and behave nicely for the user
OpenFileDialog1.Filter = "Excel files (*.xls*)|*.xls*|All files (*.*)|*.*"
OpenFileDialog1.FileName = ""
If OpenFileDialog1.ShowDialog() <> System.Windows.Forms.DialogResult.OK Then
Exit Sub
End If
Dim sr As New IO.StreamReader(OpenFileDialog1.FileName)
MessageBox.Show("You have selected" + OpenFileDialog1.FileName)
'Get all of the results before attempting to show the form
Dim listOfResults = New List(Of String)()
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Open(OpenFileDialog1.FileName)
xlWorkSheet = xlWorkBook.Worksheets(1) 'It's safer to access "the first worksheet" in case a user has renamed it.
range = xlWorkSheet.UsedRange
For rCnt = 1 To range.Rows.Count
For cCnt = 14 To range.Columns.Count
Dim tst As String = xlWorkSheet.Cells(rCnt, cCnt).Value.ToString()
'This is a neat way of saying "is my value in a list of possible values"
If (New String() {"4", "5", "6", "7", "8", "9", "10"}).Contains(tst) Then
Dim foo As String = range.Cells(rCnt, "E").Value.ToString()
listOfResults.Add(foo)
End If
Next
Next
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
'Only show Form2 after we have everything we're looking for
If listOfResults.Count > 0 Then
Form2.PopulateForm2(listOfResults)
End If
Form2.ShowDialog()
End Sub
和Form2 ...
And Form2...
Public Class Form2
'Note this is a public method on this class
Public Sub PopulateForm2(results As List(Of String))
'This could be done in the designer
DataGridView1.Columns.Clear()
DataGridView1.Columns.Add(New DataGridViewColumn())
DataGridView1.Columns.Add(New DataGridViewButtonColumn())
DataGridView1.AllowUserToAddRows = False
DataGridView1.Rows.Clear()
For count As Integer = 0 To results.Count - 1
Dim dr As DataGridViewRow = New DataGridViewRow()
Dim dc As DataGridViewCell = New DataGridViewTextBoxCell()
dc.Value = results(count)
dr.Cells.Add(dc)
Dim button As DataGridViewButtonCell = New DataGridViewButtonCell()
button.Value = "Print" '& (count + 1)
dr.Cells.Add(button)
DataGridView1.Rows.Add(dr)
Next
End Sub
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
If e.ColumnIndex = 1 Then 'i.e. the button
Dim dgv = CType(sender, DataGridView)
MessageBox.Show(String.Format("button {0} clicked. Associated Text is {1}", e.RowIndex.ToString(), dgv.Rows(e.RowIndex).Cells(0).Value))
End If
End Sub
End Class
注意我没有必须连接一个按钮点击事件 - 我已经为DataGridView使用了CellContentClick事件并且只检查了用户单击了我的Button单元格(ColumnIndex = 1)
Notice I haven't had to wire up a button click event - I've used the CellContentClick event for the DataGridView and just checked that the User has clicked on my Button cell (ColumnIndex = 1)
这篇关于如何动态显示多个标签,其值一个在另一个之下而不重复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!