اثناء تصفحي للموقع الشهير http://www.codeproject.com/ وجدت مقاله رائعه يتحدث كاتبها حول كيفية حفظ اداة DataGridView ومحتوياتها ( من صفوف وأعمده ) على شكل صورة Bmp ، قد تروقك الفكره مثلما راقتني !
طيب الفكره كلها تدور في الـ Module التالية واستخدامها لفضاء الأسماء System.Drawing.Imaging وكذلك دالة API تدعى BitBlt ، انشيء Module جديده وضع فيها السطور التالية :
Imports System.Drawing.Imaging
Module DataGrid2Bitmap
Private Declare Auto Function BitBlt Lib “gdi32.dll” _
(ByVal pHdc As IntPtr, ByVal iX As Integer, _
ByVal iY As Integer, ByVal iWidth As Integer, _
ByVal iHeight As Integer, ByVal pHdcSource As IntPtr, _
ByVal iXSource As Integer, ByVal iYSource As Integer, _
ByVal dw As System.Int32) As Boolean
Private Const SRC As Integer = &HCC0020
Public Sub ConvertDG2BMP(ByVal dg As DataGridView, ByVal sFilePath As String)
dg.Refresh()
dg.Select()
Dim g As Graphics = dg.CreateGraphics
Dim ibitMap As New Bitmap(dg.ClientSize.Width, dg.ClientSize.Height, g)
Dim iBitMap_gr As Graphics = Graphics.FromImage(ibitMap)
Dim iBitMap_hdc As IntPtr = iBitMap_gr.GetHdc
Dim me_hdc As IntPtr = g.GetHdc
BitBlt(iBitMap_hdc, 0, 0, dg.ClientSize.Width, dg.ClientSize.Height, me_hdc, 0, 0, SRC)
g.ReleaseHdc(me_hdc)
iBitMap_gr.ReleaseHdc(iBitMap_hdc)
If sFilePath = “” Then Exit Sub
ibitMap.Save(sFilePath, ImageFormat.Bmp)
End Sub
End Module
ثم في النافذه التي توجد عليها أداة الـ Datagridview وبعد عرض البيانات عليها ، نستدعي الـ Method المسماه ConvertDG2BMP ونرسل معها اسم الـ DataGridview :
Try
‘Open a file dialog for saving map documents
SaveFileDialog1.Title = “Save As BMP File”
SaveFileDialog1.Filter = “Bitmap File (*.bmp)|*.bmp”
If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.Cancel Then
Exit Sub
End If
Catch ex As Exception
Exit Sub
End Try
‘Exit if no map document is selected
Dim sFilePath As String
sFilePath = SaveFileDialog1.FileName
If sFilePath = “” Then
Exit Sub
Else
DataGrid2Bitmap.ConvertDG2BMP(DataGridView1, sFilePath)
End If
ويفضل استخدام الأداة FileSaveDialog كما بالكود أعلاه .
تجربه ناجحه بإذن الله
اخى النبهانى الرجاء شرح كيفية عدم تكرار البيانات فى عمود معين داخل الداتا قريد اثناء كتابة البيانات فى الخلايا
اهلا بك اخي سيف ، وعذرا على التأخير في التعقيبب على تعقيبك حيث انني كنت مشغول فيما مضى ولم ارى تعقيبك الا الآن !
ساعطيك الفكرة وعليك التنفيذ ، اتفقنا ؟
الفكرة تكمن في ادخال البيانات الى row جديدة في الاداة ، وبعد الانتقال الى row آخر يتم التأكد من عدم تكرارها ، في حالة تكرارها يتم الغاؤها وحذفها ( حسب حاجتك )
هل وصلتك الفكرة ؟
أخى العزيز النبهانى
أولا ابدأ حديثى بتوجيه تحيه طيبه و ابداء الشكر عن عملك جاهدا لمساعدة الاخوه المبرمجين من العرب
لكن اود ان الفت نظرك الى نقطه فى هذا المقال الا و هى انك تكبدت عناء استدعاء دوال API و التى أؤيد الاستاذ تركى العسيرى حفظه الله فى وصفه لها بأنها ” فقط للمبرمجين الشجعان ” و أضيف عليه انها مع بيئة الدوت نت للمبرمجين الانتحاريين لأسباب يطول شرحها
فى حين انك كان يمكنك تكبد هذا العناء بسهوله بالغه عن طريق استخدام الداله DrawToBitmap التابعه للأداه DataGridView و التى تؤدى الى اقتطاع جزء من الاداه او الاده كلها كصوره BMP
********
* مثال *
********
نبدأ باستيراد فضاء الاسماء NameSpace المسمى System.Drawing لاحتوائه على بعض الاصناف التى نحتاجها
Imports System.Drawing
و على فرض ان اداة الـDataGridView قد تمت تسميتها DGV و اننا وضعنا اداة صوره تدعى DGVShow
Dim B As Bitmap = New Bitmap(DGV.Width, DGV.Height) ‘ Temp Store For Bitmap
DGV.DrawToBitmap(b, New Rectangle(0, 0, DGV.ClientSize.Width, DGV.ClientSize.Height)) ‘ Copy the DataGrid to Bmp
PictureBox1.Image = b ‘ Show the bmp in image box control
و أرجو ان تكون الفكره قد وصلت و لو اخطأت بفهمك ارجو ان تبلغنى
و السلام عليكم و رحمة الله و بركاته
اهلا بك اخي Black Fox وشكرا لك على التعقيب الرائع
لقد اشرت في التدوينه الى انني نقلت الكود “نقلاً” من موقع Codeproject وبالتالي فهي ليست لي .
عموما الفكرة التي وضحتها انت هي الافضل وذلك لانها تبقينا نتعامل مع ManagedCode بشكل دائم
تحياتي
شكرا لك اخ نبهانى
لكن نصيحه
قبل ان تنقل شيئا خصوصا فيما يتعلق بالدوت نت حاول ان تتأكد انه مصمم بابسط و اكثر الطرق كفاءه
فليست الميزه فى استخدام DrawToBitmap فقط انها وفرت علينا استخدام اكواد غير مداره
بل ايضا انها صغرت حجم الكود بشكل رائع – و انها تم تصميمها خصيصا لهذا الغرض مما يؤدى بطبيعة الحال الى ان نتوقع انه تم عمل Optimization من فريق عمل مايكروسوفت عليها
احذر عزيزى من دوال API فهى اكثر خبثا مما تتصور
و رمضان كريم
شكرا جزيلا على الطريقة
طريقة أخرى
Private Sub pd_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles pd.PrintPage
e.Graphics.DrawImage(formImage, 2, -200)
End Sub
Private Sub GetFormImage()
Dim g As Graphics = Me.CreateGraphics()
Dim s As Size = Me.Size
formImage = New Bitmap(s.Width, s.Height, g)
Dim mg As Graphics = Graphics.FromImage(formImage)
Dim dc1 As IntPtr = g.GetHdc
Dim dc2 As IntPtr = mg.GetHdc
‘ added code to compute and capture the form
‘ title bar and borders
Dim widthDiff As Integer = _
(Me.Width – Me.ClientRectangle.Width)
Dim heightDiff As Integer = _
(Me.Height – Me.ClientRectangle.Height)
Dim borderSize As Integer = widthDiff \ 2
Dim heightTitleBar As Integer = heightDiff – borderSize
BitBlt(dc2, 0, 0, _
Me.ClientRectangle.Width + widthDiff, _
Me.ClientRectangle.Height + heightDiff, dc1, _
0 – borderSize, 0 – heightTitleBar, 13369376)
g.ReleaseHdc(dc1)
mg.ReleaseHdc(dc2)
End Sub
‘زر طباعة
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
GetFormImage()
pd.Print()
End Sub
‘زر اختيار طابعة
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
GetFormImage()
PrintDialog1.Document = New PrintDocument
PrintDialog1.Document = pd
If PrintDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
pd.Print()
End If
End Sub
مع اضافة PrintDialog
التصدير الى اكسل
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
‘ تصدير الى اكسل
Dim rowsTotal, colsTotal As Short
Dim I, j, iC As Short
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor
Dim xlApp As New Excel.Application
Try
Dim excelBook As Excel.Workbook = xlApp.Workbooks.Add
Dim excelWorksheet As Excel.Worksheet = CType(excelBook.Worksheets(1), Excel.Worksheet)
xlApp.Visible = True
rowsTotal = DataGridView1.RowCount – 1
colsTotal = DataGridView1.Columns.Count – 1
With excelWorksheet
.Cells.Select()
.Cells.Delete()
For iC = 0 To colsTotal
.Cells(1, iC + 1).Value = DataGridView1.Columns(iC).HeaderText
Next
For I = 0 To rowsTotal – 1
For j = 0 To colsTotal – 1
.Cells(I + 2, j + 1).value = DataGridView1.Rows(I).Cells(j).Value
Next j
Next I
.Rows(“1:1″).Font.FontStyle = “Bold”
.Rows(“1:1″).Font.Size = 10
.Cells.Columns.AutoFit()
.Cells.Select()
.Cells.EntireColumn.AutoFit()
.Cells(1, 1).Select()
End With
Catch ex As Exception
MsgBox(“Export Excel Error ” & ex.Message)
Finally
‘RELEASE ALLOACTED RESOURCES
System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default
xlApp = Nothing
End Try
End Sub
مع اضافة السطر التالي كأول سطر
Imports Excel = Microsoft.Office.Interop.Excel
واضافة reference Microsoft.Office.Interop.Excel
تم تطبيق طريقة Black Fox ودمجها مع طريقتك وتؤدي نفس النتيجة بدون اضافة موديول
Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
Dim B As Bitmap = New Bitmap(DataGridView1.Width, DataGridView1.Height) ‘ Temp Store For Bitmap
DataGridView1.DrawToBitmap(B, New Rectangle(0, 0, DataGridView1.ClientSize.Width, DataGridView1.ClientSize.Height)) ‘ Copy the DataGrid to Bmp
‘
Try
‘Open a file dialog for saving map documents
SaveFileDialog1.Title = “Save As BMP File”
SaveFileDialog1.Filter = “Bitmap File (*.bmp)|*.bmp”
If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.Cancel Then
Exit Sub
End If
Catch ex As Exception
Exit Sub
End Try
‘Exit if no map document is selected
Dim sFilePath As String
sFilePath = SaveFileDialog1.FileName
If sFilePath = “” Then
Exit Sub
Else
B.Save(sFilePath)
End If
End Sub
شكرا جزيلا لكما