Timberland Investment ROI Calculator

Investment & Land Details

Timber Details & Growth Projection

This is the overall increase in the standing timber's market value per year, combining growth and price changes.
Enter if you plan to replant immediately after final harvest, affecting final year cash flow.

Annual Operational Costs

Harvest & Sale Projections (at end of Investment Horizon)

This is the estimated gross value of timber at harvest time. If you used the appreciation rate, this should reflect that appreciated value.

Financial Parameters for Analysis

Timberland Investment Analysis Results

Please complete all previous sections and click "Calculate ROI & Metrics".

Total Initial Investment: ${timroi_formatCurrency(timroi_analysisData.results.totalInitialInvestment)}

Total Net Profit over ${inputs.investmentHorizonYears} Years: ${timroi_formatCurrency(timroi_analysisData.results.totalNetProfit)}

Return on Investment (ROI): ${timroi_analysisData.results.roi.toFixed(2)}%

Simple Payback Period: ${timroi_analysisData.results.simplePaybackPeriod}

Net Present Value (NPV) @ ${(inputs.discountRate*100).toFixed(1)}%: ${timroi_formatCurrency(timroi_analysisData.results.npv)}

Internal Rate of Return (IRR): ${timroi_analysisData.results.irr}

`; dlButton.style.display = 'block'; resTabLink.disabled = false; resTabLink.click(); } } window.timroi_downloadPDF = function() { const { jsPDF } = window.jspdf; if (!jsPDF || !timroi_analysisData.inputs || Object.keys(timroi_analysisData.inputs).length === 0) { alert("PDF library not loaded or no data to export. Please analyze first."); return; } const doc = new jsPDF(); let yPos = 20; const lineHeight = 7; const indent = 5; const pageMargin = 15; const pageWidth = doc.internal.pageSize.getWidth(); const usableWidth = pageWidth - 2 * pageMargin; doc.setFontSize(18); doc.setTextColor(44, 62, 80); // #2c3e50 doc.text("Timberland Investment ROI Analysis", pageWidth / 2, yPos, { align: 'center' }); yPos += lineHeight * 2.5; function addSection(title, dataObj, isList = false) { if (yPos > doc.internal.pageSize.getHeight() - pageMargin - 30) { doc.addPage(); yPos = pageMargin; } doc.setFontSize(13); doc.setFont(undefined, 'bold'); doc.setTextColor(85, 107, 47); // #556b2f doc.text(title, pageMargin, yPos); yPos += lineHeight * 1.5; doc.setFontSize(10); doc.setFont(undefined, 'normal'); doc.setTextColor(51,51,51); if (isList) { dataObj.forEach(item => { if (yPos > doc.internal.pageSize.getHeight() - pageMargin - lineHeight) { doc.addPage(); yPos = pageMargin; } doc.text(item, pageMargin + indent, yPos); yPos += lineHeight; }); } else { for (const [key, value] of Object.entries(dataObj)) { if (yPos > doc.internal.pageSize.getHeight() - pageMargin - lineHeight) { doc.addPage(); yPos = pageMargin; } let formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase()); let valStr = String(value); if (typeof value === 'number') { if (key.toLowerCase().includes('rate') || key.toLowerCase().includes('percent') || key.toLowerCase().includes('escalation') || key.toLowerCase().includes('roi') || key.toLowerCase().includes('appreciation')) { valStr = value.toFixed(2) + '%'; } else { valStr = timroi_formatCurrency(value); } } else if (key === 'irr' || key === 'simplePaybackPeriod') { valStr = String(value); } doc.text(`${formattedKey}:`, pageMargin + indent, yPos); doc.text(valStr, pageMargin + indent + 85, yPos, {align: 'left', maxWidth: usableWidth - (indent + 85)}); yPos += lineHeight * 1.1; } } yPos += lineHeight * 0.5; } const inputSummaryForPdf = { "Property Name": timroi_analysisData.inputs.propertyName, "Location Scope": timroi_analysisData.inputs.locationScope, "Land Area (Acres)": timroi_analysisData.inputs.landAreaAcres, "Land Purchase Cost": timroi_analysisData.inputs.landPurchaseCost, "Initial Timber Value": timroi_analysisData.inputs.initialTimberValue, "Acquisition Costs": timroi_analysisData.inputs.acquisitionCosts, "Investment Horizon (Years)": timroi_analysisData.inputs.investmentHorizonYears, "Primary Timber Species": timroi_analysisData.inputs.primarySpecies, "Timber Value Appreciation Rate (% p.a.)": (timroi_analysisData.inputs.timberValueAppreciationPa * 100), "Replanting Cost (End of Horizon)": timroi_analysisData.inputs.replantingCost, "Annual Property Taxes": timroi_analysisData.inputs.propertyTaxesAnnual, "Annual Management Fees": timroi_analysisData.inputs.managementFeesAnnual, "Other Annual Costs": timroi_analysisData.inputs.otherCostsAnnual, "Annual Costs Escalation Rate (%)": (timroi_analysisData.inputs.annualCostsEscalation * 100), "Projected Timber Sale Value (Gross)": timroi_analysisData.inputs.projectedTimberSaleValue, "Harvesting Costs (% of Sale)": (timroi_analysisData.inputs.harvestingCostsPercent * 100), "Projected Land Sale Value (Gross)": timroi_analysisData.inputs.projectedLandSaleValue, "Land Sale Costs (% of Sale)": (timroi_analysisData.inputs.landSaleCostsPercent*100), "Discount Rate (%)": (timroi_analysisData.inputs.discountRate * 100) }; addSection("Input Parameters Summary", inputSummaryForPdf); const resultsSummaryForPdf = { "Total Initial Investment": timroi_analysisData.results.totalInitialInvestment, "Total Net Profit": timroi_analysisData.results.totalNetProfit, "Return on Investment (ROI)": timroi_analysisData.results.roi, "Simple Payback Period": timroi_analysisData.results.simplePaybackPeriod, "Net Present Value (NPV)": timroi_analysisData.results.npv, "Internal Rate of Return (IRR)": timroi_analysisData.results.irr }; addSection("Key Investment Metrics", resultsSummaryForPdf); let cashFlowSampleForPdf = ["Year | Op. Costs ($) | Net Harvest ($) | Net Land Sale ($) | Replant ($) | Net CF ($)"]; cashFlowSampleForPdf.push(`0 | --- | --- | --- | --- | ${timroi_formatCurrency(-timroi_analysisData.results.totalInitialInvestment)}`); const yearsToShowInPdf = Math.min(timroi_analysisData.annual_cash_flows.length, 5); for(let i = 0; i < yearsToShowInPdf; i++) { const cf = timroi_analysisData.annual_cash_flows[i]; // Only show harvest/land sale/replant for the final year in this simplified sample let harvestText = (cf.year === timroi_analysisData.inputs.investmentHorizonYears) ? timroi_formatCurrency(cf.netTimberRevenue) : "---"; let landSaleText = (cf.year === timroi_analysisData.inputs.investmentHorizonYears) ? timroi_formatCurrency(cf.netLandSaleRevenue) : "---"; let replantText = (cf.year === timroi_analysisData.inputs.investmentHorizonYears) ? timroi_formatCurrency(-cf.replantingCost) : "---"; cashFlowSampleForPdf.push( `${cf.year} | ` + `${timroi_formatCurrency(cf.operatingCosts)} | ` + `${harvestText} | ` + `${landSaleText} | ` + `${replantText} | ` + `${timroi_formatCurrency(cf.netCashFlow)}` ); } if (timroi_analysisData.annual_cash_flows.length > 5) { // If more than 5 years, show ellipsis and last year cashFlowSampleForPdf.push("..."); const lastCf = timroi_analysisData.annual_cash_flows[timroi_analysisData.annual_cash_flows.length - 1]; cashFlowSampleForPdf.push( `${lastCf.year} | ` + `${timroi_formatCurrency(lastCf.operatingCosts)} | ` + `${timroi_formatCurrency(lastCf.netTimberRevenue)} | ` + `${timroi_formatCurrency(lastCf.netLandSaleRevenue)} | ` + `${timroi_formatCurrency(-lastCf.replantingCost)} | ` + `${timroi_formatCurrency(lastCf.netCashFlow)}` ); } if (yPos > doc.internal.pageSize.getHeight() - pageMargin - (cashFlowSampleForPdf.length * lineHeight) - (lineHeight*2.5) ) { doc.addPage(); yPos = pageMargin; } doc.setFont(undefined,'normal'); doc.setFontSize(8); addSection("Annual Cash Flow Summary (Sample)", cashFlowSampleForPdf, true); doc.save('Timberland_Investment_ROI_Analysis.pdf'); }
Scroll to Top