Create Spreadsheet Like Grid with SwiftUI

I have some test code in which I am attempting to create a spreadsheet style grid with data. The code creates a grid but I am unable to get the bottom border of one row to overlap the top border of the row below it but I can get it to work left to right with padding using a negative trailing border. Any assistance would be appreciated. Below is the code:

import SwiftUI
struct DateAndClose {
    let date: Date
    let close: Double
}
func BuildArray() -> [DateAndClose] {
    var dataArray: [DateAndClose] = []
    dataArray.append(DateAndClose(date: Date(), close: 123.4))
    dataArray.append(DateAndClose(date: Date() + 10, close: 245.8))
    dataArray.append(DateAndClose(date: Date() + 30, close: 329.3))
    dataArray.append(DateAndClose(date: Date() + 45, close: 438.9))
    return dataArray
}
struct Test: View {
    let heading: String
    var body: some View {
        let moArray: [DateAndClose] = BuildArray()
        Text("")
        Text(heading)
            .font(.system(size: 18, weight: .bold, design: .default))
            .foregroundColor(.blue)
            .padding(.trailing, 24)
        Text("")
        List(moArray, id: \.date) { element in
            ListRow1(element: element)
        }
        .frame(width: 250)
        .background(Color.gray)
        Spacer()
    }
}
struct ListRow1: View {
    let element: DateAndClose
    var body: some View {
        let theDate = dateToStringFormatter.string(from: element.date)
        let theClose = String(format: "$%.2f", element.close )
        let frameWidth: CGFloat = 100
        let frameHeight: CGFloat = 25
        let trailingPadding: CGFloat = -8.55
        let bottomPadding: CGFloat = -4.8
        HStack(){
            Spacer()
            Text(theDate)
                .font(.system(size: 14, weight: .regular, design: .default))
                .background(.white)
                .frame(width: frameWidth, height: frameHeight, alignment: .center)
                .border(.black, width: 1)
                .padding(.trailing, trailingPadding)
                .padding(.bottom, bottomPadding)
            Text(theClose)
                .font(.system(size: 14, weight: .regular, design: .default))
                .background(.white)
                .frame(width: frameWidth, height: frameHeight, alignment: .center)
                .border(.black, width: 1)
                .padding(.bottom, bottomPadding)
            Spacer()
        }
    }
}
let dateToStringFormatter: DateFormatter = {
    let result = DateFormatter()
    result.dateFormat = "MM/dd/yy"
    result.timeZone = TimeZone(secondsFromGMT: 0)
    return result
}()

Answered by ChrisMH in 724684022

It appears that I should have been using GridItems. They have solved my problem. Below is the code:

struct DateAndCloseTable: View {
    let containerData: [CommonAttributes]
    let heading: String
    let verticalSpacing: CGFloat = 0
    let frameWidth: CGFloat = 100
    let frameHeight: CGFloat = 25
    let horizontalSpacing: CGFloat = 0
    let trailingPadding: CGFloat = 45
    let bottomPadding: CGFloat = -2
    let columns = [
        GridItem(.fixed(75), spacing: 0),
        GridItem(.fixed(75), spacing: 0)
    ]
    var body: some View {
        Text("")
        Text(heading)
            .font(.system(size: 18, weight: .bold, design: .default))
            .foregroundColor(.blue)
            .padding(.trailing, 24)
        Text("")
        ScrollView {
            let lastRowIndex: Int = containerData.count - 1
            LazyVGrid(columns: columns, alignment: .center, spacing: verticalSpacing){
                ForEach((0...lastRowIndex), id: \.self) { index in
                    let theDate = dateToStringFormatter.string(from: containerData[index].date!)
                    let theClose = String(format: "$%.2f", containerData[index].close )
                    Text(theDate)
                        .font(.system(size: 14, weight: .regular, design: .default))
                        .frame(width: frameWidth, height: frameHeight, alignment: .center)
                        .background(.white)
                        .border(.black, width: 1)
                        .padding(.trailing, trailingPadding)
                        .padding(.bottom, bottomPadding)
                    Text(theClose)
                        .font(.system(size: 14, weight: .regular, design: .default))
                        .frame(width: frameWidth, height: frameHeight, alignment: .center)
                        .background(.white)
                        .border(.black, width: 1)
                        .padding(.bottom, bottomPadding)
                }
                Text("")
                Text("")
                Text("")
            } // end lazy v grid
            .padding(.horizontal)
        } // end of scroll view
    }
}


Accepted Answer

It appears that I should have been using GridItems. They have solved my problem. Below is the code:

struct DateAndCloseTable: View {
    let containerData: [CommonAttributes]
    let heading: String
    let verticalSpacing: CGFloat = 0
    let frameWidth: CGFloat = 100
    let frameHeight: CGFloat = 25
    let horizontalSpacing: CGFloat = 0
    let trailingPadding: CGFloat = 45
    let bottomPadding: CGFloat = -2
    let columns = [
        GridItem(.fixed(75), spacing: 0),
        GridItem(.fixed(75), spacing: 0)
    ]
    var body: some View {
        Text("")
        Text(heading)
            .font(.system(size: 18, weight: .bold, design: .default))
            .foregroundColor(.blue)
            .padding(.trailing, 24)
        Text("")
        ScrollView {
            let lastRowIndex: Int = containerData.count - 1
            LazyVGrid(columns: columns, alignment: .center, spacing: verticalSpacing){
                ForEach((0...lastRowIndex), id: \.self) { index in
                    let theDate = dateToStringFormatter.string(from: containerData[index].date!)
                    let theClose = String(format: "$%.2f", containerData[index].close )
                    Text(theDate)
                        .font(.system(size: 14, weight: .regular, design: .default))
                        .frame(width: frameWidth, height: frameHeight, alignment: .center)
                        .background(.white)
                        .border(.black, width: 1)
                        .padding(.trailing, trailingPadding)
                        .padding(.bottom, bottomPadding)
                    Text(theClose)
                        .font(.system(size: 14, weight: .regular, design: .default))
                        .frame(width: frameWidth, height: frameHeight, alignment: .center)
                        .background(.white)
                        .border(.black, width: 1)
                        .padding(.bottom, bottomPadding)
                }
                Text("")
                Text("")
                Text("")
            } // end lazy v grid
            .padding(.horizontal)
        } // end of scroll view
    }
}


What is the following line?

let containerData: [CommonAttributes]

Please explain.

Create Spreadsheet Like Grid with SwiftUI
 
 
Q