This is working for me:
" Similar to the goto command, but for characters.
" index is 1-based, the start of the file.
function! GotoCharacter(index)
call search('\m\%^\_.\{'.a:index.'}', 'es')
" The search() function above counts a newline as 1 character even if it is
" actually 2. Therefore adjust the cursor position when newlines are
" 2 characters.
if &ff ==# 'dos'
let [_whichwrap, &whichwrap] = [&whichwrap, "h,l"]
let delta = wordcount().cursor_chars - a:index
while delta != 0
" Cannot land on a newline character.
if (delta == -1 || delta == -2) && col('.') == col('$') - 1
break
endif
execute "normal! ".delta.(delta > 0 ? 'h' : 'l')
let delta = wordcount().cursor_chars - a:index
endwhile
let &whichwrap = _whichwrap
endif
endfunction
ff=dos
as they miscount the linebreak characters.