Here's my modified copy (with some slight differences):
https://www.dropbox.com/s/r9vv8oib6blxia3/P...bearz.xlsm?dl=0Modifications I've made:
Added macro to obtain fund prices (Options -> Customize Ribbon -> Developer tab)If you are not comfortable with code,
I highly suggest that you don't use this file and let polarzbearz look at the code and verify that it doesn't do anything malicious then include it into his version. As this file contains a macro, it will trigger security warnings and you will need to enable macros in order to use it. You have to do this only once.

The macro code in this file is
slightly different than the one I posted above. The differences in this file is just that I added a message indicator saying what is being updated so that if something fails you'll know which fund is causing the problem:
» Click to show Spoiler - click again to hide... «
Code here for auditing:
» Click to show Spoiler - click again to hide... «
CODE
Sub GetFundPrices()
Set WS = Worksheets("Investment Details")
Set htm = CreateObject("htmlFile")
Set XML = CreateObject("msxml2.xmlhttp")
procform.Show (vbModeless)
Dim i As Long
Dim lastRow As Long
lastRow = WS.Range("C:C").Find(What:="*exit*", LookIn:=xlValues).Row
For i = 1 To lastRow
'Update Row Values'
If WS.Cells(i, 1).Value = "1" Then
Dim fundName As String
fundName = WS.Cells(i, 3).Value
'Update form'
procform.lbl_fundName.Caption = fundName
'Obtain data'
XML.Open "GET", "http://www.fundsupermart.com.my/main/fundinfo/dailyPricesHistory.tpl?id=" & fundName, False
XML.send
If XML.ReadyState = 4 And XML.Status = 200 Then
htm.body.innerHTML = XML.responsetext
On Error GoTo ErrHandler:
'Get first row of data'
Set FirstRow = htm.getElementsByTagName("tr")(2).Children
procform.Repaint
'Update date value'
WS.Cells(i, 4).Value = FirstRow(3).innerText
'Update NAV'
WS.Cells(i, 9).Value = FirstRow(2).FirstChild().innerText
End If
End If
Next i
'Hide procform'
procform.Hide
Exit Sub
ErrHandler:
MsgBox ("Cannot load data. Either the FSM Code is incorrect or FundSuperMart is down.")
procform.Hide
End Sub
Changed "Investment Details" table into range (Table Design tab -> Convert to Range)Since I just want to insert rows by "Select rows -> right click -> insert copied cells" *and* I don't really want to have tons of placeholder rows, I converted it to a normal range. The only downside to this, is that Excel will not autofill the formulas for you. However, it is really really simple to do that manually:
- Shift + spacebar (This selects the row if its not already selected)
- Ctrl + D (This takes the formula from the row above and fills it into the current row)
» Click to show Spoiler - click again to hide... «
I removed the dummy values for the IRR calculationsSince I don't have any retired funds... I understand they're there to
fix a summary bugChanged unit amount rounding orderAs mentioned in my
first post, this rounding appears to match what is shown in FSM's site. I have not encountered any differences between my units and the units shown on FSM's website
yet... but my dataset is a lot smaller than all the seasoned investors here so please do check. If you had to use Transaction Adjustments to adjust your units before, this
should eliminate the need for it.
I'm currently modifying your original source (the first one which was provided), mainly on the ErrHandling part - so that the code continues to execute (for subsequent fund updates) even if there was error, and provides a summary at end of execution.
CODE
Sub GetFundPrices()
Set WS = Worksheets("Investment Details")
Set htm = CreateObject("htmlFile")
Set XML = CreateObject("msxml2.xmlhttp")
Dim i As Long
Dim lastRow As Long
'Search for the last line item (column A) with value 0
lastRow = WS.Range("A:A").Find(What:="0", After:=WS.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False).Row
'Executing logs placeholder
Dim logs As String
logs = "Status logs:" & vbNewLine
'Set a Number of Updates counter, starting from zero before going into the loop
Dim successfulUpdate As Long
Dim totalUpdate As Long
sucessfulUpdate = 0
totalUpdate = 0
'From first row all the way to the row containing the value *exit*'
'From first row all the way to the last row of line item 0
For i = 1 To lastRow
'If this row is a group header row (Column A has a value of 1)'
If WS.Cells(i, 1).Value = "1" Then
' total update counter +1
totalUpdate = totalUpdate + 1
'Get the fund code'
Dim fundName As String
fundName = WS.Cells(i, 3).Value
'Download the correct price list'
XML.Open "GET", "http://www.fundsupermart.com.my/main/fundinfo/dailyPricesHistory.tpl?id=" & fundName, False
On Error GoTo EndHandler: ' terminate if error in connecting
XML.send
If XML.ReadyState = 4 And XML.Status = 200 Then
htm.body.innerHTML = XML.responsetext
On Error GoTo ErrHandler:
'On Error Resume Next:
'Get all 4 cells in the first row of data'
Set FirstRow = htm.getElementsByTagName("tr")(2).Children
'Update date value from 4th table cell of first row'
WS.Cells(i, 4).Value = FirstRow(3).innerText
'Update NAV value from the DIV element in the 3rd table cell of first row'
WS.Cells(i, 9).Value = FirstRow(2).FirstChild().innerText
' successful update counter +1
successfulUpdate = successfulUpdate + 1
logs = logs & vbNewLine & fundName & vbTab & "OK!"
SkipBlocks:
'skip everything above from "On Error GoTo ErrHandler:" block
End If
End If
Next i
MsgBox logs
Exit Sub
ErrHandler:
MsgBox ("Cannot load data. Either the FSM Code is incorrect or FundSuperMart is down." & i)
' fail counter, messages
logs = logs & vbNewLine & fundName & vbTab & "ERROR!"
'i = i + 1
'Resume Next
Resume SkipBlocks:
EndHandler:
MsgBox ("Unable to connect to FSM website. Please try again later.")
End Sub
Good work on your side, never thought about fetching the NAV price from FSM directly