Excel VBA - navigate through worksheet using 'next' and 'previous' buttons - forms

I have an Excel form which reads data from each row of an 80-row worksheet and populates each cell into a textbox.
The code for the initial form is below.
Private Sub UserForm_Initialize()
txtbox_revri_idnum.Text = Worksheets("Risk&Issues").Range("A4").Value
txtbox_revri_projname.Text = Worksheets("Risk&Issues").Range("B4").Value
txtbox_revri_isrefnum.Text = Worksheets("Risk&Issues").Range("C4").Value
txtbox_revri_riskrefnum.Text = Worksheets("Risk&Issues").Range("D4").Value
...
txtbox_revri_projname.SetFocus
End Sub
Ideally, what I'd like to do is when the 'next' button is pressed, the next row (A5, B5, C5, D5...) is parsed into an array, and the Range is updated with the next row's data. Conversely, the 'previous' button would go in the reverse direction (A3, B3, C3, D3...). Essentially, I'd like to navigate up and down the worksheet reviewing the entire row with each cell in a new textbox.
I've tried all sorts of combinations of VBA (baring in mind I'm new to VBA although do have some Java and PHP experience). The code I have for my 'next' button current has the code below.
Private Sub button_revri_next_Click()
txtbox_revri_idnum.Text = ActiveCell.Next.Text
...
End Sub
Thank you... I know you guys are way more smarter than me!

You can use .Offset to achieve what you want.
TRIED AND TESTED
Dim i As Long, j As Long
Dim rng As Range
Private Sub UserForm_Initialize()
Set rng = Worksheets("Risk&Issues").Range("A4")
i = 0: j = 1
txtbox_revri_idnum.Text = rng.Offset(i).Value
txtbox_revri_projname.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_isrefnum.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_riskrefnum.Text = rng.Offset(i, j).Value: j = j + 1
'
'
txtbox_revri_projname.SetFocus
End Sub
'~~> Next Button
Private Sub button_revri_next_Click()
i = i + 1: j = 1
If i > (Sheets("Risk&Issues").Rows.Count - 4) Then
MsgBox "Max rows Reached"
Exit Sub
End If
txtbox_revri_idnum.Text = rng.Offset(i).Value
txtbox_revri_projname.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_isrefnum.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_riskrefnum.Text = rng.Offset(i, j).Value: j = j + 1
'
'
txtbox_revri_projname.SetFocus
End Sub
Similarly Previous Button
'~~> Previous Button
Private Sub button_revri_prev_Click()
i = i - 1: j = 1
If i < 0 Then
MsgBox "1st Row Reached"
Exit Sub
End If
txtbox_revri_idnum.Text = rng.Offset(i).Value
txtbox_revri_projname.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_isrefnum.Text = rng.Offset(i, j).Value: j = j + 1
txtbox_revri_riskrefnum.Text = rng.Offset(i, j).Value: j = j + 1
'
'
txtbox_revri_projname.SetFocus
End Sub

Related

How to split word files by the number of characters

Could you anybody help me how to split word file by character!
I can't find any way to split word files by the number of characters on the internet!
For example, to split a document into 500-character blocks:
Sub SplitDocument()
Application.ScreenUpdating = False
Dim Rng As Range, i As Long, j As Long
Const Char As Long = 500
With ActiveDocument
' Process each character block
For i = 1 To Int(.Characters.Count / Char)
j = j + 1
' Get the character block
Set Rng = .Range((i - 1) * Char, i * Char)
' Copy the character block
Rng.Copy
Rng.Collapse wdCollapseEnd
Call NewDoc(ActiveDocument, (i - 1) * Char + 1, j)
Next
If Rng.End < .Range.End Then
i = i + 1: j = j + 1
Rng.End = .Range.End
' Copy the range
Rng.Copy
Rng.Collapse wdCollapseEnd
Call NewDoc(ActiveDocument, (i - 1) * Char + 1, j)
End If
End With
Set Rng = Nothing
Application.ScreenUpdating = True
End Sub
Sub NewDoc(DocSrc As Document, i As Long, j As Long)
Dim DocTgt As Document, HdFt As HeaderFooter
' Create the output document
Set DocTgt = Documents.Add(Visible:=False)
With DocTgt
' Paste contents into the output document, preserving the formatting
.Range.PasteAndFormat (wdFormatOriginalFormatting)
' Replicate the headers & footers
For Each HdFt In DocSrc.Sections(DocSrc.Characters(i).Sections(1).Index).Headers
.Sections(1).Headers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
For Each HdFt In DocSrc.Sections(DocSrc.Characters(i).Sections(1).Index).Footers
.Sections(1).Footers(HdFt.Index).Range.FormattedText = HdFt.Range.FormattedText
Next
' Save & close the output document
.SaveAs FileName:=Split(DocSrc.FullName, ".doc")(0) & "_" & j & ".docx", _
FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
Set DocTgt = Nothing: Set DocSrc = Nothing
End Sub

Remove Marks on Charts

I have a problem with my code, I want to evaluate a Report with Charts.
What my Macro currently does is, Create for every single column a Row for a nominal, upper, lower tolerance. Then It creates with this values a chart.
After this it starts with the Sorting and then it removes the Marker Points, but here my Problems already start.
I would like to create the charts later for example on pos A100 or A50 or something.
Then the Marker Points, I would like to keep the Points on the result line but not on the 3 created, but I found no way 
Remove the Markers, but it removes all, i would really like to remove them only for
FullSeriesCollection(2).format.Line
FullSeriesCollection(3).format.Line
FullSeriesCollection(4).format.Line
Would be nice if someone would have an idea.. :)
Thanks in advance,
' Unload UFormTools
UFormTools.Hide
Application.ScreenUpdating = False
Sheets("Original Values").Select
Dim lngC As Long, lngR As Long
Dim i As Long
Dim c As Byte
Application.ScreenUpdating = False
With ActiveSheet
lngC = (.Cells(17, 4).End(xlToRight).Column - 4) * 4
For i = 4 To lngC Step 4
lngR = .Cells(.Rows.Count, i).End(xlUp).Row
For c = 1 To 3
.Columns(i + c).EntireColumn.Insert
Next c
.Cells(17, i).AutoFill Destination:=.Range(.Cells(17, i), .Cells(17, i + 3)), Type:=xlFillCopy
.Range(.Cells(28, i + 1), .Cells(lngR, i + 1)).Value = .Cells(18, i).Value
.Range(.Cells(28, i + 2), .Cells(lngR, i + 2)).Value = .Cells(18, i).Value + .Cells(19, i).Value
.Range(.Cells(28, i + 3), .Cells(lngR, i + 3)).Value = .Cells(18, i).Value + .Cells(20, i).Value
.Shapes.AddChart2(332, xlLineMarkers).Select
With ActiveChart
.SetSourceData Source:=Union(ActiveSheet.Range(ActiveSheet.Cells(17, i), ActiveSheet.Cells(17, i + 3)), _
ActiveSheet.Range(ActiveSheet.Cells(28, i), ActiveSheet.Cells(lngR, i + 3)))
' .Legend.Delete
.ChartTitle.Text = ActiveSheet.Cells(17, i).Value
.ChartTitle.format.TextFrame2.TextRange.Characters.Text = ActiveSheet.Cells(17, i).Value
With .ChartTitle.format.TextFrame2.TextRange.Characters(1, Len(ActiveSheet.Cells(17, i).Value)).ParagraphFormat
.TextDirection = msoTextDirectionLeftToRight
.Alignment = msoAlignCenter
End With
With .FullSeriesCollection(3).format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With .FullSeriesCollection(4).format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
With .FullSeriesCollection(2).format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
.Visible = msoTrue
.DashStyle = msoLineDash
.Weight = 1.5
End With
With .FullSeriesCollection(1).format.Line
.Visible = msoTrue
.Weight = 3
End With
.FullSeriesCollection(1).Smooth = True
.Axes(xlValue).MinimumScaleIsAuto = True
.Axes(xlValue).MinimumScaleIsAuto = True
End With
Next i
End With
' Sort and Arrange Charts, but another Position to Start would be nice.. (for example A100)
Dim MyWidth As Single, MyHeight As Single
Dim NumWide As Long
Dim iChtIx As Long, iChtCt As Long
MyWidth = 300
MyHeight = 200
NumWide = 4
iChtCt = ActiveSheet.ChartObjects.Count
For iChtIx = 1 To iChtCt
With ActiveSheet.ChartObjects(iChtIx)
.Width = MyWidth
.Height = MyHeight
.Left = ((iChtIx - 1) Mod NumWide) * MyWidth
.Top = Int((iChtIx - 1) / NumWide) * MyHeight
End With
Next
' Remove the Markers, but it removes all, i would really like to remove them only for
' FullSeriesCollection(2).format.Line
' FullSeriesCollection(3).format.Line
' FullSeriesCollection(4).format.Line
Dim cht As ChartObject
Dim srs As Series
Dim MarkerCount As Long
For Each cht In ActiveSheet.ChartObjects
cht.Activate
For Each srs In ActiveChart.SeriesCollection
If srs.MarkerStyle <> xlMarkerStyleNone Then
srs.MarkerStyle = xlMarkerStyleNone
MarkerCount = MarkerCount + 1
End If
Next srs
Next cht
Range("A1").Select
Application.ScreenUpdating = True

enable/disable checkbox by its resident cell location

I want to disable/enable a checkbox in an excel sheet using vba based on the value/conditon of another checkbox. I cannot use the checkbox name, I want to use it's cell location in reference to the cell location of the checkbox that is enabling/disabling it. something like this:
Sub Software2()
Dim myRange As Range
Set myRange = Range(ActiveSheet.Shapes(Application.Caller).TopLeftCell.Address)
If ActiveSheet.Shapes(Application.Caller).ControlFormat.Value = 1 Then
myRange.Interior.ColorIndex = 35
myRange.Offset(0, 1).Interior.ColorIndex = 35
myRange.Offset(0, 2).Interior.ColorIndex = 35
myRange.Offset(1, 1).Interior.ColorIndex = 44
myRange.Offset(1, 2).Interior.ColorIndex = 44
myRange.Offset(2, 1).Interior.ColorIndex = 44
myRange.Offset(2, 2).Interior.ColorIndex = 44
Else
myRange.Interior.ColorIndex = 44
myRange.Offset(0, 1).Interior.ColorIndex = 44
myRange.Offset(0, 2).Interior.ColorIndex = 44
myRange.Offset(1, 1).Interior.ColorIndex = 0
myRange.Offset(1, 2).Interior.ColorIndex = 0
myRange.Offset(2, 1).Interior.ColorIndex = 0
myRange.Offset(2, 2).Interior.ColorIndex = 0
'ActiveSheet.Shapes(location of other checkbox).ControlFormat.Enabled = 0
'ActiveSheet.Shapes(location of other checkbox).ControlFormat.Enabled = 0
End If
End Sub
Here's a demo of how to find a control by its position relative to a range.
TopLeftCell is a bit finicky since the control might drift a bit to the top and/or left and so not get found. Using relative Top/Left position is a bit more robust.
You could even combine the two - depends on the relative size of the cell and the control.
Option Explicit
Sub Tester()
Dim cb
Set cb = GetControlFromRange(Range("B6"))
If Not cb Is Nothing Then
Debug.Print cb.Name
'toggle enabled
With cb.ControlFormat
.Enabled = Not .Enabled
End With
End If
End Sub
Function GetControlFromRange(rng As Range) As Object
Const POS_DELTA_MAX As Long = 10
Dim c As Object, s As Shape
For Each s In rng.Parent.Shapes
If s.Type = msoFormControl Then
'using TopLeftCell
' If Not Application.Intersect(s.TopLeftCell, rng) Is Nothing Then
' Set c = s
' Exit For
' End If
'using position
If Abs(s.Top - rng.Top) < POS_DELTA_MAX And _
Abs(s.Left - rng.Left) < POS_DELTA_MAX Then
Set c = s
Exit For
End If
End If
Next s
Set GetControlFromRange = c
End Function

Align series by value in DevExpress XtraCharts

I have a DevExpress XtraChart object with several series, all of type: line.
I have a requirement from a client to align the series by the max value of each series. This is without regard to the attached axis, has anyone done this before?
Although I was interested in displaying this on the chart element, the 'work' was done on the underlying DataSet.
I was able to achieve this by looping through the series collection, deriving the max value of the first series, through a SQL query, and then each subsequent series, and noting the difference, and then adding or subtracting the difference at the DataSet level.
Here's the code:
Private Sub cbAlignPeaks_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbAlignPeaks.CheckedChanged
Dim dt As DataTable = chart.DataSource
Dim Row() As Data.DataRow
Dim s As Series = Nothing
Dim dtr As DataTableReader = Nothing
Dim maxTimeGet, maxTimeSet, diff As Decimal
Me.Cursor = Cursors.WaitCursor
If cbAlignPeaksPre.Checked Then
For i As Integer = 0 To chartPreTim.Series.Count - 1
s = chartPreTim.Series(i)
If _offsets.Count = chartPreTim.Series.Count - 1 Then
If i > 0 Then
diff = _offsets(s.DataFilters(0).Value)
Row = dt.Select("BORING_NAME = '" & s.Name & "'")
For k As Integer = 0 To Row.Count - 1
Row(k)("TIME_SEC") = Row(k)("TIME_SEC") + diff
Next
End If
Else
If i = 0 Then 'get adjustment info
dtr = getDetectorMax(s.DataFilters(0).Value, cbDetectors.Text, timType.PRE) ' <-- getDetectorMax runs a SQL query returning the max value
If dtr.Read Then
maxTimeGet = dtr("TIME_SEC")
End If
Else 'set adjustment info
dtr = Nothing
dtr = getDetectorMax(s.DataFilters(0).Value, cbDetectors.Text, timType.PRE)
If dtr.Read Then
maxTimeSet = dtr("TIME_SEC")
End If
If maxTimeGet > maxTimeSet Then
diff = maxTimeGet - maxTimeSet
_offsets.Add(s.DataFilters(0).Value, diff)
Row = dt.Select("BORING_NAME = '" & s.DataFilters(0).Value & "'")
For k As Integer = 0 To Row.Count - 1
Row(k)("TIME_SEC") = Row(k)("TIME_SEC") + diff
Next
Else
diff = maxTimeSet - maxTimeGet
_offsets.Add(s.DataFilters(0).Value, diff * -1)
Row = dt.Select("BORING_NAME = '" & s.DataFilters(0).Value & "'")
For k As Integer = 0 To Row.Count - 1
Row(k)("TIME_SEC") = Row(k)("TIME_SEC") - diff
Next
End If
End If
End If
Next
Else
For i As Integer = 1 To chartPreTim.Series.Count - 1 ' We skip item 0 as that's the baseline
s = chartPreTim.Series(i)
diff = _offsets(s.DataFilters(0).Value)
Row = dt.Select("BORING_NAME = '" & s.DataFilters(0).Value & "'")
For k As Integer = 0 To Row.Count - 1
Row(k)("TIME_SEC") = Row(k)("TIME_SEC") - diff
Next
Next
End If
chartPreTim.RefreshData()
chartPreTim.Refresh()
Me.Cursor = Cursors.Default
End Sub

Run time error 9 when using arrary in Macro

I have been using the followng Macro and it works fine:
Sub PremTable()
Dim i, m, j As Integer
Dim PDFDiv, PDFClass, PDFSex, PDFPlan, LimAge As Variant
Dim FlagD, FlagC, Band, FlagP, FlagB, IssAge, Dur As Integer
PDFClass = Array("N", "S")
PDFSex = Array("M", "F")
PDFDiv = Array("G", "E")
PDFPlan = Array(10, 20, 30)
LimAge = Array(70, 60, 50)
j = 0
For FlagD = 1 To 2
Range("div").Value = PDFDiv(FlagD)
For FlagP = 1 To 3
Range("plan").Value = PDFPlan(FlagP)
For Band = 1 To 3
Range("band").Value = Band
For FlagS = 1 To 2
Range("sex").Value = PDFSex(FlagS)
For FlagC = 1 To 2
Range("class").Value = PDFClass(FlagC)
m = 18
For i = 1 To Range("LimAge").Value - 17
Range("IssAge").Offset(i + j, 0) = m
Range("age").Value = Range("IssAge").Offset(i + j, 0)
Worksheets("input").Range("J4:J76").Copy
Worksheets("Premium Tables").Range("M1").Offset(i + j, 0).PasteSpecial xlPasteValues, Transpose:=True
Range("DIV2").Offset(i + j, 0) = Range("Div")
Range("PLAN2").Offset(i + j, 0) = Range("plan")
Range("BAND2").Offset(i + j, 0) = Range("band")
Range("SEX2").Offset(i + j, 0) = Range("sex")
Range("CLASS2").Offset(i + j, 0) = Range("class")
m = m + 1
Next i
j = j + i - 1
Next FlagC
Next FlagS
Next Band
Next FlagP
Next FlagD
End Sub
Now I have another very similar spreatsheet that I want to use this macro to creat tables, but it always give me the "run time error 9" for all of the arrays having text format variables (for example: Range("class").Value = PDFClass(FlagC) causing an runtime error 9)
Please advise! Thanks very much!