Android POI - Excel - добавить категорию (строковое значение) в оси YAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android POI - Excel - добавить категорию (строковое значение) в оси Y

Сообщение Anonymous »

Код: Выделить всё

chart.ctChart.plotArea.scatterChartList.lastOrNull()?.let { sc ->
// markers only
val st = sc.scatterStyle ?: sc.addNewScatterStyle()
st.`val` = STScatterStyle.MARKER

sc.serList.forEachIndexed { i, ser ->
// κρύψε γραμμή
val sp = if (ser.isSetSpPr) ser.spPr else ser.addNewSpPr()
val ln = if (sp.isSetLn) sp.ln else sp.addNewLn()
if (!ln.isSetNoFill) ln.addNewNoFill()

// ΣΚΛΗΡΟ reset dLbls
if (ser.isSetDLbls) ser.unsetDLbls()
val dLbls = ser.addNewDLbls()

// ΜΟΝΟ ένα point label στο idx=0, με ρητό κείμενο από helper κελί
val dl = dLbls.addNewDLbl()
dl.addNewIdx().`val` = 0L

val ref = CellReference(drawSheet.sheetName, legendRow0 + i, legendCol, true, true)
dl.addNewTx().addNewStrRef().f = ref.formatAsString()

// όλα τα flags OFF
dl.addNewShowSerName().`val` = false
dl.addNewShowVal().`val` = false
dl.addNewShowCatName().`val` = false
dl.addNewShowLegendKey().`val` = false
dl.addNewShowPercent().`val` = false
dl.addNewShowBubbleSize().`val` = false

// θέση μόνο για αυτό το point
dl.addNewDLblPos().`val` = STDLblPos.L
}

// καθάρισε chart-level dLbls για σιγουριά
if (sc.isSetDLbls) sc.unsetDLbls()
}
< /code>
Этот код добавляет метки для каждой точки каждой серии. < /p>
fun eventsTimelineScatter(
drawSheet: XSSFSheet,   // ΠΟΥ ζωγραφίζει (π.χ. "Charts")
dataSheet: XSSFSheet,   // ΑΠΟ ΠΟΥ διαβάζει (π.χ.  "PlotData")
lastRow: Int,
title: String,
anchorCols: IntRange,
anchorRows: IntRange,
xCol: Int,              // στήλη χρόνου (Excel serial, numeric)
typeCol: Int            // στήλη κατηγορίας (String)
) {
data class Cat(val key: String, val display: String)
fun norm(raw: String?): Cat {
val d = (raw ?: "Unknown").trim().replace(Regex("\\s+"), " ")
return Cat(d.lowercase().ifEmpty { "unknown" }, d.ifEmpty { "Unknown" })
}

val byType = mutableMapOf>()
val keyToDisplay = mutableMapOf()
val laneOf = mutableMapOf()
fun lane(k: String) = laneOf.getOrPut(k) { laneOf.size + 1 }.toDouble()

var xMin = Double.POSITIVE_INFINITY
var xMax = Double.NEGATIVE_INFINITY
for (r in 1..lastRow) {
val row = dataSheet.getRow(r) ?: continue
val cat = norm(row.getCell(typeCol)?.toString())
val x = row.getCell(xCol)?.numericCellValue ?: continue
byType.getOrPut(cat.key) { mutableListOf() }.add(x to lane(cat.key))
keyToDisplay.putIfAbsent(cat.key, cat.display)
if (x < xMin) xMin = x
if (x >  xMax) xMax = x
}
if (byType.isEmpty()) return

// legend helper cells (τίτλοι σειρών από κελί)
val legendCol = (anchorCols.last + 2).coerceAtLeast(24)
val legendRow0 = anchorRows.first
val keysInOrder = keyToDisplay.keys.sortedBy { keyToDisplay[it]!!.lowercase() }
keysInOrder.forEachIndexed { i, k ->
val row = drawSheet.getRow(legendRow0 + i) ?: drawSheet.createRow(legendRow0 + i)
row.createCell(legendCol).setCellValue(keyToDisplay[k])
}

val drawing = drawSheet.createDrawingPatriarch() as XSSFDrawing
val anchor = drawing.createAnchor(0,0,0,0, anchorCols.first, anchorRows.first, anchorCols.last+1, anchorRows.last+1)
val chart = drawing.createChart(anchor) as XSSFChart

val xAxis = chart.createValueAxis(AxisPosition.BOTTOM).apply {
crosses = AxisCrosses.MIN
majorTickMark = AxisTickMark.OUT
minorTickMark = AxisTickMark.NONE
tickLabelPosition = AxisTickLabelPosition.LOW
}
val yAxis = chart.createValueAxis(AxisPosition.LEFT).apply {
majorTickMark = AxisTickMark.NONE
minorTickMark = AxisTickMark.NONE
tickLabelPosition = AxisTickLabelPosition.NONE
}

val data = chart.createData(ChartTypes.SCATTER, xAxis, yAxis) as XDDFScatterChartData
data.setVaryColors(false)
try { data.style = ScatterStyle.MARKER } catch (_: Throwable) {}

// σειρές (μία ανά κατηγορία)
keysInOrder.forEachIndexed { i, k ->
val pts = byType[k]!!.sortedBy { it.first }
val xs = XDDFDataSourcesFactory.fromArray(pts.map { it.first }.toTypedArray())
val ys = XDDFDataSourcesFactory.fromArray(pts.map { it.second }.toTypedArray())
val s = data.addSeries(xs, ys) as XDDFScatterChartData.Series
val ref = CellReference(drawSheet.sheetName, legendRow0 + i, legendCol, true, true)
s.setTitle(null, ref)
s.setMarkerStyle(MarkerStyle.CIRCLE)
s.setMarkerSize(7)
s.isSmooth = false
}

chart.plot(data)
chart.setTitleText(title)
chart.setTitleOverlay(false)

// --- CT tweaks ---
// 5) CT: markers only + 1 label (series title) ΜΟΝΟ στο πρώτο point κάθε σειράς
// 5) CT: markers only + 1 label (from cell) ΜΟΝΟ στο πρώτο point κάθε σειράς
chart.ctChart.plotArea.scatterChartList.lastOrNull()?.let { sc ->
// markers only
val st = sc.scatterStyle ?: sc.addNewScatterStyle()
st.`val` = STScatterStyle.MARKER

sc.serList.forEachIndexed { i, ser ->
// κρύψε γραμμή
val sp = if (ser.isSetSpPr) ser.spPr else ser.addNewSpPr()
val ln = if (sp.isSetLn) sp.ln else sp.addNewLn()
if (!ln.isSetNoFill) ln.addNewNoFill()

// ΣΚΛΗΡΟ reset dLbls
if (ser.isSetDLbls) ser.unsetDLbls()
val dLbls = ser.addNewDLbls()

// ΜΟΝΟ ένα point label στο idx=0, με ρητό κείμενο από helper κελί
val dl = dLbls.addNewDLbl()
dl.addNewIdx().`val` = 0L

val ref = CellReference(drawSheet.sheetName, legendRow0 + i, legendCol, true, true)
dl.addNewTx().addNewStrRef().f = ref.formatAsString()

// όλα τα flags OFF
dl.addNewShowSerName().`val` = false
dl.addNewShowVal().`val` = false
dl.addNewShowCatName().`val` = false
dl.addNewShowLegendKey().`val` = false
dl.addNewShowPercent().`val` = false
dl.addNewShowBubbleSize().`val` = false

// θέση μόνο για αυτό το point
dl.addNewDLblPos().`val` = STDLblPos.L
}

// καθάρισε chart-level dLbls για σιγουριά
if (sc.isSetDLbls) sc.unsetDLbls()
}

// Legend
chart.getOrAddLegend().apply { position = LegendPosition.TOP_RIGHT; isOverlay = false }

// Gridlines στον Χ
chart.ctChart.plotArea.valAxList.forEach { ax ->
if (ax.axPos.`val` == STAxPos.B && !ax.isSetMajorGridlines) ax.addNewMajorGridlines()
}

// X axis: datetime format + λίγα ticks
chart.ctChart.plotArea.valAxList.firstOrNull { it.axPos.`val` == STAxPos.B }?.let { xAx ->
val nf = if (xAx.isSetNumFmt) xAx.numFmt else xAx.addNewNumFmt()
nf.formatCode = "yyyy-mm-dd HH:mm:ss"; nf.sourceLinked = false

val range = if (xMax.isFinite() && xMin.isFinite() && xMax >  xMin) xMax - xMin else 1.0
val desiredTicks = 6
val step = range / (desiredTicks - 1)
val sca = if (xAx.scaling!=null) xAx.scaling else xAx.addNewScaling()
if (sca.isSetMin) sca.unsetMin()
if (sca.isSetMax) sca.unsetMax()
sca.addNewMin().setVal(if (xMin.isFinite()) xMin else 0.0)
sca.addNewMax().setVal(if (xMax.isFinite()) xMax else 1.0)
if (xAx.isSetMajorUnit) xAx.unsetMajorUnit()
xAx.addNewMajorUnit().setVal(step)
}

// Y axis: lanes 1..N, χωρίς labels, tick ανά lane
val lanes = max(laneOf.size, 1)
chart.ctChart.plotArea.valAxList.firstOrNull { it.axPos.`val` == STAxPos.L }?.let { yAx ->
(if (yAx.isSetDelete) yAx.delete else yAx.addNewDelete()).setVal(false)
val sca = if (yAx.scaling!=null) yAx.scaling else yAx.addNewScaling()
if (sca.isSetMin) sca.unsetMin()
if (sca.isSetMax) sca.unsetMax()
sca.addNewMin().setVal(0.5)
sca.addNewMax().setVal(lanes + 0.5)
if (yAx.isSetMajorUnit) yAx.unsetMajorUnit()
yAx.addNewMajorUnit().setVal(1.0)
}

// (προαιρετικά: “ψημένα” Y labels σε κελιά αριστερά — το έχεις ήδη commented)
}

Я хочу заменить значение индекса y, но этот код, который я написал, добавьте метки в каждой точке вместо этого только для первой точки.
Любой совет?>

Подробнее здесь: https://stackoverflow.com/questions/797 ... -in-y-axis
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»