Spanish Abrir Excel .xls

TheFalcon

Active Member
Licensed User
Longtime User
Buenas como siempre, Espero que estén todos bien.
Recurro a vosotros por que estoy atrancado.
Estoy intentando ABRIR un Excel, el cual creo y muestro en un Table. pero no me va, pensaba que era por que lo abria justo despues de generar le Table, pero me he puesto un boton directamente para abrir el fichero y no hay manera, lo intento de dos modos.
El fichero esta en la ruta /storage/emulated/0/archivo_04-11-2022.xls"

Los dos modos que uso son

PROVIDER:
   Dim ruta As String ="/storage/emulated/0"
    Dim archivo As String ="archivo_04-11-2022.xls"

    Dim uri As String
    Dim ik As Intent
    uri = File.Combine(ruta,"/" & archivo)
    Log(uri)
    ik.Initialize(ik.ACTION_VIEW, uri)
    ik.SetType("application/vnd.ms-excel")
    ik.WrapAsIntentChooser("Escoge Programa para Abrir")
    StartActivity(ik)
        
'--------------  2 MODO --------------------------------


    Dim archivo As String ="archivo_04-11-2022.xls"

    provider.Initialize

    File.Copy(File.DirRootExternal&"/", archivo, provider.SharedFolder, archivo)
    'File.Copy(ruta, archivo, provider.SharedFolder, archivo)
    Dim in As Intent
    provider.SetFileUriAsIntentData(in, archivo)
    'Type must be set after calling SetFileUriAsIntentData
    in.SetType("application/xls")
    StartActivity(in)

Con el primer método escojo el programa con el que abrir, pero me dice que he de cerrar el EXCEL y guardarlo antes. de hay que pensara que el error era al abrirlo al crear el table.
Pero incluso poniéndolo en un botón directamente y el exel ya existiendo me lo dice


con el 2º me da java.lang.RuntimeException: Object should first be initialized (Intent).

Os pongo el Manifest, resumido los permisos de almacenamiento

Manifest:
AddManifestText(
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="29"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
    
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
CreateResourceFromFile(Macro, Themes.LightTheme)
'End of default text.



CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)



'**** instalar apk
AddApplicationText(
  <provider
  android:name="android.support.v4.content.FileProvider"
  android:authorities="$PACKAGE$.provider"
  android:exported="false"
  android:grantUriPermissions="true">
  <meta-data
  android:name="android.support.FILE_PROVIDER_PATHS"
  android:resource="@xml/provider_paths"/>
  </provider>
)

CreateResource(xml, provider_paths,
   <files-path name="name" path="shared" />
)

SetApplicationAttribute(android:requestLegacyExternalStorage, true) ' de sdk 28 para abajo

AddPermission(android.permission.READ_EXTERNAL_STORAGE) ' Allows an application to read from external storage.

'AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)


gracias por vuestro tiempo
 

TheFalcon

Active Member
Licensed User
Longtime User
en vez de la librería fileprovider , estoy usando un modulo fileprovider

Modulo:
'v1.00
Sub Class_Globals
    Public SharedFolder As String
    Public UseFileProvider As Boolean
    Private rp As RuntimePermissions
End Sub

Public Sub Initialize
    Dim p As Phone
    If p.SdkVersion >= 24 Or File.ExternalWritable = False Then
        UseFileProvider = True
        SharedFolder = File.Combine(File.DirInternal, "shared")
        File.MakeDir("", SharedFolder)
    Else
        UseFileProvider = False
        SharedFolder = rp.GetSafeDirDefaultExternal("shared")
    End If
    Log($"Using FileProvider? ${UseFileProvider}"$)
End Sub

'Returns the file uri.
Public Sub GetFileUri (FileName As String) As Object
   
    If UseFileProvider = False Then
        Dim uri As JavaObject
        Return uri.InitializeStatic("android.net.Uri").RunMethod("parse", Array("file://" & File.Combine(SharedFolder, FileName)))
    Else
        Dim f As JavaObject
        f.InitializeNewInstance("java.io.File", Array(SharedFolder, FileName))
        Dim fp As JavaObject
        Dim context As JavaObject
        context.InitializeContext
        fp.InitializeStatic("android.support.v4.content.FileProvider")
        Return fp.RunMethod("getUriForFile", Array(context, Application.PackageName & ".provider", f))
    End If
End Sub

'Replaces the intent Data field with the file uri.
'Resets the type field. Make sure to call Intent.SetType after calling this method
Public Sub SetFileUriAsIntentData (Intent As Intent, FileName As String)
    Dim jo As JavaObject = Intent
    jo.RunMethod("setData", Array(GetFileUri(FileName)))
    Intent.Flags = Bit.Or(Intent.Flags, 1) 'FLAG_GRANT_READ_URI_PERMISSION
End Sub

En principio el modo me es indiferente, lo que necesito es poder abrir desde la APP el excel que genero, ya sea en Excel o con cualquier otro programa compatible
 

TheFalcon

Active Member
Licensed User
Longtime User
Si pongo el archivo en la tarjeta SD , si me funciona poniendo la ruta a mano.

B4X:
Dim ruta As String ="/storage/5893-BF29"
    Dim archivo As String ="archivo_04-11-2022.xls"

    Dim uri As String
    Dim ik As Intent
    uri = File.Combine(ruta,"/" & archivo)
    Log(uri)
    ik.Initialize(ik.ACTION_VIEW, uri)
    ik.SetType("application/vnd.ms-excel")
    ik.WrapAsIntentChooser("Escoge Programa para Abrir")
    StartActivity(ik)

Con lo cual puede ser de permisos de File.DirRootExternal.

ese mismo código si la ruta es File.DirRootExternal , al escoger abrir con Excel me dice "No puede abrir el archivo" Intente Guardar el archivo en el dispositivo y a continuación abrirlo."
 

angel_

Well-Known Member
Licensed User
Longtime User
Y si antes de abrir el archivo lo copias a la carpeta xui.defaultfolder y lo abres desde ahí
 

TheFalcon

Active Member
Licensed User
Longtime User
¿Qué librería estás utilizando?
No tampoco, me he asegurado que lo copia bien, haciendo un
B4X:
If File.Exists(xui.DefaultFolder, archivo) = True Then ToastMessageShow("EXISTE",True)

B4X:
    Dim uri As String
    Dim ik As Intent
    
    File.Copy(File.DirRootExternal,archivo,xui.DefaultFolder,archivo)
'    uri = File.Combine(File.DirRootExternal,"/" & archivo)
    uri = xui.DefaultFolder &"/" & archivo
    Log(uri)
    If File.Exists(xui.DefaultFolder, archivo) = True Then ToastMessageShow("EXISTE",True)
    ik.Initialize(ik.ACTION_VIEW, uri)
    ik.SetType("application/vnd.ms-excel")
    ik.WrapAsIntentChooser("Escoge Programa para Abrir")
    StartActivity(ik)
después de copiar para verificar que lo copia, y antes de abrirlo.
 

josejad

Expert
Licensed User
Longtime User
Hola TheFalcon

Como siempre, creo que la forma más fácil en la que te podemos ayudar, es que subas un pequeño proyecto de ejemplo.

saludos,
 

josejad

Expert
Licensed User
Longtime User
Hola TheFalcon:

No veo en tu app que pidas ningún permiso para acceder a File.dirdefaultexternal.
Tienes que leer un poco sobre los permisos y las distintas carpetas a las que puedes acceder.

Este hilo te puede aclarar un poco las cosas, lee los enlaces a Runtime Permissions, targetSDKVersion, Save as...

Necesitas realmente acceder a DirDefaultExternal?
En tu programa simplemente sustituyendo las dos apariciones de File.DirDefaultExternal por xui.DefaultFolder ya funciona (bueno, el intent no llega a funcionar del todo, pero aparece lo de existe y me empieza a abrir excel

Por cierto, en tu proyecto estás usando la clase FileProvider, que ya se convirtió en una librería interna. Por tanto, deberías eliminar la clase de tu proyecto y seleccionar en su lugar la librería.

saludos,
 

TheFalcon

Active Member
Licensed User
Longtime User
Gracias José como siempre.
Me es indiferente donde acceda la aplicación la verdad, tanto me da que sea DirRootExternal , como dirdefaultexternal. ya que la aplicación lo que le da al usuario es la posibilidad de abrir el Excel al generarlo.

Eliminare el fileprovider y lo cargare desde la librería.
Mañana miro el enlace que me mandas y lo pruebo y te digo.
Muchas Gracias y Buenas Noches
 

TheFalcon

Active Member
Licensed User
Longtime User
nada, He probado varias cosas.

con xui.DefaultFolder NO me lo crea en la ruta

/data/user/0/com.Fjo.Citius/files/archivo.xls


con File.DirRootExternal SI lo crea, pero no lo abre

/storage/emulated/0/archivo.xls



con File.DirDefaultExternal SI lo crea pero no lo abre.

/storage/emulated/0/Android/data/com.Fjo.Citius/files/archivo.xls


Luego elimine el Modulo de File provider, y use la libreria y con el codigo
B4X:
Dim archivo As String ="archivo.xls"

    provider.Initialize
 
    File.Copy(File.DirRootExternal, archivo, provider.SharedFolder, archivo)
    Log(provider.SharedFolder)
    Dim in As Intent
 
    provider.SetFileUriAsIntentData(in, archivo)
    'Type must be set after calling SetFileUriAsIntentData
in.SetType("application/xls")
    StartActivity(in)

Tanto si uso DirRoot o dir default, no me lo abre.

No se que permiso me falta he leido los Hilos y los tengo todo, a lo mejor lo que no tengo bien es

B4X:
Sub CanWriteToSystemSettings As Boolean
    Dim p As Phone
    If p.SdkVersion >= 23 Then
        Dim ctxt As JavaObject
        ctxt.InitializeContext
        Dim settings As JavaObject
        settings.InitializeStatic("android.provider.Settings.System")
        Return settings.RunMethod("canWrite", Array(ctxt))
    End If
    Return True
End Sub

O

B4X:
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    If Result Then
        Dim dir As String = File.DirRootExternal
   
        If CanWriteToSystemSettings = True Then
            Dim in As Intent
            in.Initialize("android.settings.action.MANAGE_WRITE_SETTINGS", "package:" & Application.PackageName)
            StartActivity(in)
            Wait For Activity_Resume
            If CanWriteToSystemSettings = False Then
                Log("no permission...")
                Return
            End If
        End If
       
    End If
 

josejad

Expert
Licensed User
Longtime User
Hola:

prueba este proyecto

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private fp As FileProvider
    Dim archivo As String
End Sub

Public Sub Initialize
    B4XPages.GetManager.LogEvents = True
    fp.Initialize
    archivo = "archivo.xls"
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    If File.Exists(fp.SharedFolder,archivo) = False Then
        File.Copy(File.DirAssets,archivo,fp.SharedFolder,archivo)
    End If
    Log("shared: " & fp.SharedFolder)
End Sub

'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.

Private Sub Button1_Click
    Dim uri As String
    Dim i As Intent

    uri = fp.GetFileUri(archivo)
    Log(uri)
    i.Initialize(i.ACTION_VIEW, "")
    fp.SetFileUriAsIntentData(i, archivo)
    'Type must be set after calling SetFileUriAsIntentData
    i.SetType("application/vnd.ms-excel")
    i.WrapAsIntentChooser ("Escoge Programa para Abrir")
    StartActivity(i)
End Sub

Tras varias pruebas, ha sido este hilo el que me ha dado la solución
 

Attachments

  • Excel.zip
    17.9 KB · Views: 65
Last edited:
Top