JavascriptProva

venerdì 23 novembre 2018

Aggiustamenti del foglio Excel dopo avervi incollato la tabella di Word

Una volta incollata la tabella da Word, si fanno due tipi di aggiustamenti:
  1. il testo, che non va più messo a capo
  2. le celle, che vanno espanse a seconda del testo contenuto.
Ecco, divisa in due, la Sub che ne deriva:
Sub aggiustamentipostincollaggio()
'
' aggiustamentipostincollaggio Macro
' Macro registrata il 24/11/2018 da Windows User
'

'
    Columns("D:D").Select
    With Selection
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    Columns("D:D").EntireColumn.AutoFit
End Sub

Ora bisogna ridurre tutte le celle-firma.
Semplificando il risultato della registrazione della macro, dovrebbe restare questo:
Sub formattacellefirma()
'
' formattacellefirma Macro
' Macro registrata il 24/11/2018 da Windows User
'

'
    Columns("E:AH").Select
    Selection.ColumnWidth = 2.43
End Sub
Ora provo tutte le funzioni da capo.
In fondo, sono solo tre!
Sì, funzionano alla grande!

Impostiamo la pagina per copiare la tabella su Excel

Vado su Excel.
Incollo tutta la tabella di sana pianta.
Sub impostapagina()
'
' impostapagina Macro
' Macro registrata il 24/11/2018 da Windows User
'

'
    With ActiveSheet.PageSetup
        .PrintTitleRows = ""
        .PrintTitleColumns = ""
    End With
    ActiveSheet.PageSetup.PrintArea = ""
    With ActiveSheet.PageSetup
        .LeftHeader = ""
        .CenterHeader = ""
        .RightHeader = ""
        .LeftFooter = ""
        .CenterFooter = ""
        .RightFooter = ""
        .LeftMargin = Application.InchesToPoints(0.787401575)
        .RightMargin = Application.InchesToPoints(0.787401575)
        .TopMargin = Application.InchesToPoints(0.984251969)
        .BottomMargin = Application.InchesToPoints(0.984251969)
        .HeaderMargin = Application.InchesToPoints(0.5)
        .FooterMargin = Application.InchesToPoints(0.5)
        .PrintHeadings = False
        .PrintGridlines = False
        .PrintComments = xlPrintNoComments
        .CenterHorizontally = False
        .CenterVertically = False
        .Orientation = xlLandscape
        .Draft = False
        .PaperSize = xlPaperA4
        .FirstPageNumber = xlAutomatic
        .Order = xlDownThenOver
        .BlackAndWhite = False
        .Zoom = False
        .FitToPagesWide = 1
        .FitToPagesTall = 1
        .PrintErrors = xlPrintErrorsDisplayed
    End With
End Sub
Una quantità enorme di informazioni quando sarebbe sufficiente soltanto la parte marcata in rosso...

giovedì 22 novembre 2018

Codice delle macro per l'inserimento di tabelle in Word (Word 2003)

Ecco: questa la devo fare in tempi rapidi.
Creare una tabella di 35 colonne e 31 righe.
Questo comando dà al foglio un orientamento orizzontale.
ActiveDocument.PageSetup.Orientation = wdOrientLandscape
e ho trovato anche l'inverso, quello che lo riporta verticale:
ActiveDocument.PageSetup.Orientation = wdOrientPortrait.

Comunque il foglio mi serve Landscape.

Ora tracciamo la tabella tutta a celle uguali. Ne inizio la registrazione cercando di ricordare le modalità applicate prima a causa del "mouse invalido" che si crea durante la registrazione delle macro...

Ecco tutta la macro:
Sub tabella()
'
' tabella Macro
' Macro registrata il 23/11/2018 da Windows User
'
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=31, NumColumns _
        :=35, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitWindow
    With Selection.Tables(1)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
End Sub
Cominciamo a spezzettarla...

Ecco, ho individuato un codice minimo che aggiunge una tabella a un foglio:
Sub tabella()
'
' tabella Macro
' Macro registrata il 23/11/2018 da Windows User
'
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=31, NumColumns _
        :=35, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitWindow

End Sub
Devo vedere cosa significa DefaultTableBehavior...

Rivedo il codice completo:
Sub tabella()
'
' tabella Macro
' Macro registrata il 23/11/2018 da Windows User
'
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=31, NumColumns _
        :=35, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitWindow
    With Selection.Tables(1)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
End Sub
Vediamo il form per la creazione della tabella dove c'è la scelta fra varie opzioni, alle quali sicuramente si riferisce gran parte del codice "non essenziale".



Mi pare che avevo scelto "Adatta alla pagina", ma adesso ci vado in modo sistematico: andiamo con queste impostazioni di default:
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitFixed
    With Selection.Tables(1)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
Ora modifico "Larghezza fissa colonne" che porto da "Auto" a 1.5:
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitFixed
    With Selection.Tables(1)
        .Columns.PreferredWidth = CentimetersToPoints(1.5)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With


Ora modifico la seconda voce: scelgo "Adatta al contenuto":
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitContent
    With Selection.Tables(1)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
Mentre in quelle precedenti era:
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitFixed
Scegliendo l'opzione "Adatta alla pagina":
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitWindow
    With Selection.Tables(1)
        If .Style <> "Griglia tabella" Then
            .Style = "Griglia tabella"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
Ecco.
Schiacciando "Griglia tabella" si apre questa finestra:



...nella quale sono comprese queste istruzioni:
    ActiveDocument.Tables.Add Range:=Selection.Range, NumRows:=2, NumColumns:= _
        5, DefaultTableBehavior:=wdWord9TableBehavior, AutoFitBehavior:= _
        wdAutoFitFixed
    With Selection.Tables(1)
        If .Style <> "Tabella a colori 1" Then
            .Style = "Tabella a colori 1"
        End If
        .ApplyStyleHeadingRows = True
        .ApplyStyleLastRow = True
        .ApplyStyleFirstColumn = True
        .ApplyStyleLastColumn = True
    End With
Ormai è quasi tutto chiaro.

venerdì 9 novembre 2018

Salvataggio floatingView e removeView (immagini in overlay)

Le strade si dividono: da una parte, l'apprendimento teorico di tutto il sistema delle floatingViews, dall'altra le modifiche funzionali alla mia applicazione N-S.
Salvo la MainActivity, notevole specialmente per il "trucchetto" che evita di dover riavviare l'applicazione dopo i permessi a runtime:
public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Runnable runnable = new Runnable() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                if(Settings.canDrawOverlays(getApplicationContext())){
                    Intent i = new Intent(getApplicationContext(),MainActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(i);
                }else{
                    new Handler().postDelayed(this,1000);
                }
            }
        };


        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
                new Handler().postDelayed(runnable,1000);
            }
        }

        Intent intent=new Intent(getApplicationContext(),Servizio.class);
        startService(intent);

    }

}


Salvo il codice dello studio teorico:
public class Servizio extends Service {
    int x_init_coord, y_init_coord, x_margin, y_margin;
    long time_start, time_end;
    private View mFloatingView;
    private View removeView;
    private WindowManager windowManager;
    private WindowManager.LayoutParams wParams;

    public Servizio() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();


        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        addFloatingWidgetView();
        addRemoveWidgetView();



    }

    private void addFloatingWidgetView() {
        mFloatingView = LayoutInflater.from(this).inflate(R.layout.widget, null);

        wParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        wParams.gravity = Gravity.TOP | Gravity.LEFT;
        wParams.x = 0;
        wParams.y = 100;

        windowManager.addView(mFloatingView, wParams);


        mFloatingView.setOnTouchListener(new View.OnTouchListener() {
            int x_init_coord, y_init_coord;
            int x_margin, y_margin;
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) mFloatingView.getLayoutParams();
                int x_coord = (int) event.getRawX();
                int y_coord = (int) event.getRawY();
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:

                        time_start = System.currentTimeMillis();

                        x_margin = layoutParams.x;
                        y_margin = layoutParams.y;
                        x_init_coord = x_coord;
                        y_init_coord = y_coord;
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        int x_diff = x_coord - x_init_coord;
                        int y_diff = y_coord - y_init_coord;
                        int x_destination = x_margin + x_diff;
                        int y_destination = y_margin + y_diff;
                        layoutParams.x = x_destination;
                        layoutParams.y = y_destination;
                        windowManager.updateViewLayout(view,layoutParams);
                        return true;
                    case MotionEvent.ACTION_UP:
                        int x_diff_up = x_coord - x_init_coord;
                        int y_diff_up = y_coord - y_init_coord;
                        if(Math.abs(x_diff_up) < 5  && Math.abs(y_diff_up) < 5){
                            time_end = System.currentTimeMillis();
                            if(time_end - time_start < 300){
                                System.out.println("E' UN CLICK");
                            }
                        }
                }
                return false;
            }
        });
    }




    private void addRemoveWidgetView(){

        LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
        removeView = inflater.inflate(R.layout.removewidget,null);

        WindowManager.LayoutParams removeParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );
        removeParams.gravity = Gravity.TOP | Gravity.LEFT;

        windowManager.addView(removeView,removeParams);



    }


}


Salvo i due xml che vengono "inflatati" per la floatingView e per la removeView:

floatingVIew:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <!--Root container-->
    <RelativeLayout
        android:id="@+id/root_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:ignore="UselessParent">

        <ImageView
            android:adjustViewBounds="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src = "@drawable/facciadascemo"/>


    </RelativeLayout>

</FrameLayout> 


removeView:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <!--Root container-->
    <RelativeLayout
        android:id="@+id/root_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:ignore="UselessParent">

        <ImageView
            android:adjustViewBounds="true"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src = "@drawable/removeimage"/>


    </RelativeLayout>

</FrameLayout> 

giovedì 8 novembre 2018

Codice essenziale per una floating image in overlay in android

Ecco ricostruito il codice per muovere una floating image in overlay:
        mFloatingView.setOnTouchListener(new View.OnTouchListener() {
            int x_init_coord, y_init_coord;
            int x_margin, y_margin;
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) mFloatingView.getLayoutParams();
                int x_coord = (int) event.getRawX();
                int y_coord = (int) event.getRawY();
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        x_margin = layoutParams.x;
                        y_margin = layoutParams.y;
                        x_init_coord = x_coord;
                        y_init_coord = y_coord;
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        int x_diff = x_coord - x_init_coord;
                        int y_diff = y_coord - y_init_coord;
                        int x_destination = x_margin + x_diff;
                        int y_destination = y_margin + y_diff;
                        layoutParams.x = x_destination;
                        layoutParams.y = y_destination;
                        windowManager.updateViewLayout(view,layoutParams);
                        return true;
                }
                return false;
            }
        });

lunedì 5 novembre 2018

Codice per un service con una floatingView in overlay

Ecco tutto il codice del Service che fa apparire una floating view in overlay:
public class Servizio extends Service {
    int deltaX, deltaY;
    private View mFloatingView;
    private WindowManager windowManager;
    private WindowManager.LayoutParams wParams;
    public Servizio() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        wParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        wParams.gravity = Gravity.TOP | Gravity.LEFT;
        wParams.x=300;
        wParams.y=600;

        mFloatingView=LayoutInflater.from(this).inflate(R.layout.widget,null);

        windowManager.addView(mFloatingView,wParams);


        mFloatingView.setOnTouchListener(new View.OnTouchListener() {


            @Override
            public boolean onTouch(View view, MotionEvent event) {

                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:

                        deltaX = (int) event.getRawX() - wParams.x;
                        deltaY = (int) event.getRawY() - wParams.y;

                        return true;

                    case MotionEvent.ACTION_MOVE:
                        wParams.x =(int)event.getRawX()-deltaX;
                        wParams.y = (int)event.getRawY()-deltaY;
                        windowManager.updateViewLayout(mFloatingView,wParams);
                        return true;
                }
                return false;
            }
        });
        


    }
}
Questo codice viene chiamato dall'activity principale in questo modo:
        Intent intent=new Intent(getApplicationContext(),Servizio.class);
        startService(intent);

Per completezza, scrivo per intero il codice della MainActivity in modo da mostrare il codice per i permessi a runtime del disegno in overlay (non valido e quindi ignorato, come già mostrato nel video) in un dispositivo con API < 23.
public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Runnable runnable = new Runnable() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                if(Settings.canDrawOverlays(getApplicationContext())){
                    Intent i = new Intent(getApplicationContext(),MainActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(i);
                }else{
                    new Handler().postDelayed(this,1000);
                }
            }
        };


        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
                new Handler().postDelayed(runnable,1000);
            }
        }

        Intent intent=new Intent(getApplicationContext(),Servizio.class);
        startService(intent);

    }

}
Il codice è quello marcato in bianco su blu.

domenica 4 novembre 2018

Ancora sul trucco per non riavviare l'applicazione dopo i permessi a runtime per l'overlay

Views in overlay.
Con l'occasione, ripasso il "trucco" per non dover riavviare il programma una volta concesso il permesso a runtime per gli overlay.

Iniziamo da qui:
public class MainActivity extends AppCompatActivity {
    
    Intent i;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

}
Ora, devo inserire il codice per i permessi.
Innanzitutto non deve mancare mai il classico permesso nel manifest!
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.antonello.studiooverlay">
    <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name" 


Quindi ci sono i permessi a runtime.
Approfitto dell'occasione per ripassare un po' i "meccanismi" della cosa...

Se l'API è uguale o superiore alla 23, se contemporaneamente non è impostato il permesso di Overlay (!Settings.canDrawOverlays(getApplicationContext())), si crea un intent avente per parametri ACTION_MANAGE_OVERLAY_PERMISSION e Uri.parse(...col nome del package...).
Questo dovrebbe bastare a cambiare le carte in tavola dopo aver chiamato startActivity(intent).
Però sempre dopo aver riavviato l'applicazione.

Ecco il codice:
        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
            }
        }
Ora applichiamo il "trucco".
public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Runnable runnable = new Runnable() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                if(Settings.canDrawOverlays(getApplicationContext())){
                    Intent i = new Intent(getApplicationContext(),MainActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(i);
                }else{
                    new Handler().postDelayed(this,1000);
                }
            }
        };


        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
                new Handler().postDelayed(runnable,1000);
            }
        }

    }

}
Ora realizzo un video con due emulatori aventi rispettivamente API 22 e API 23 per metterne in luce le differenze di comportamento.